home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / net / sun4.md / netHppi.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  132KB  |  4,465 lines

  1. /* 
  2.  * netHppi.c --
  3.  *
  4.  *    Routines for handling the TMC 29K cards.
  5.  *
  6.  * Copyright 1992 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/net/sun4.md/netHppi.c,v 1.4 92/10/26 12:17:41 elm Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include <sprite.h>
  21. #include <vm.h>
  22. #include <vmMach.h>
  23. #include <mach.h>
  24. #include <netUltraInt.h>
  25. #include <dev/ultra.h>
  26. #include <netHppi.h>
  27. #include <netHppiInt.h>
  28. #include <dev/hppi.h>
  29. #include <fmt.h>
  30. #include <sync.h>
  31. #include <dbg.h>
  32. #include <rpcPacket.h>
  33. #include <assert.h>
  34. #include <list.h>
  35.  
  36. /*
  37.  * "Borrow" the Vax format for the format of the Ultranet adapter (it
  38.  * is really a 386.  We need to swap some of the words in the
  39.  * diagnostic and information structures.
  40.  */
  41.  
  42. #define NET_ULTRA_FORMAT FMT_VAX_FORMAT
  43.  
  44. /*
  45.  * The transmit and receive queues are in the dual port RAM on the
  46.  * link board.
  47.  */
  48. #define QUEUES_IN_DUALPORT_RAM
  49.  
  50. Boolean        netHppiDebug = FALSE;
  51. Boolean        netHppiTrace = FALSE;
  52. int        netHppiMapThreshold = NET_ULTRA_MAP_THRESHOLD;
  53. static unsigned char netHppiConnPar[] = {0xc6, 0x10, 0x0c, 0x00,
  54.                          0xff, 0xff, 0xff, 0xff,
  55.                          0x00, 0x00, 0x00, 0x00,
  56.                          0x00, 0x00, 0x00, 0x00};
  57. static int    numHppiInterfaces = 0;
  58. static NetHppiState* hppiState[NET_HPPI_MAX_INTERFACES];
  59. static int    packetsSunk = 0;
  60. static Time    sinkStartTime;
  61. static Time    sinkEndTime;
  62.  
  63. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  64.  
  65. #define WAIT_FOR_REPLY(ptr, count) {        \
  66.     int    i;                    \
  67.     for(i = (count); i > 0; i -= 100) {        \
  68.     MACH_DELAY(100);            \
  69.     if (*((volatile int *)ptr) != 0) {    \
  70.         break;                \
  71.     }                    \
  72.     }                        \
  73. }
  74.  
  75. #define WAIT_FOR_BIT_CLEAR(ptr, count, mask) {        \
  76.     int i;                        \
  77.     for (i = (count); i > 0; i -= 100) {        \
  78.     if ((*((volatile int *)ptr) & (mask)) == 0) {    \
  79.         break;                    \
  80.     }                        \
  81.     MACH_DELAY (100);                \
  82.     }                            \
  83. }
  84.  
  85.  
  86. /*
  87.  * This is a "wildcard" address that matches any TL address.
  88.  * Once again we have to lie about the size of a Net_Address
  89.  * since the adapter will puke if it isn't 7 bytes (why have it
  90.  * if you can't change it?).
  91.  */
  92. static Net_UltraTLAddress    wildcardAddress = 
  93.                 {7, NET_ULTRA_TSAP_SIZE};
  94.  
  95. /*
  96.  * Forward declarations.
  97.  */
  98.  
  99. static char         *GetStatusString _ARGS_ ((int status));
  100. static Sync_Condition    dsndTestDone;
  101. static Sync_Condition    drcvTestDone;
  102. static Sync_Condition    iopOutputDone;
  103. static int        dsndCount;
  104.  
  105. static void        InitQueues _ARGS_((NetHppiState *statePtr));
  106. static void        StandardDone _ARGS_((Net_Interface *interPtr, 
  107.                 NetUltraXRBInfo *infoPtr));
  108. static ReturnStatus    NetHppiSendDgram _ARGS_((Net_Interface *interPtr,
  109.                 Net_Address *netAddressPtr, int count,
  110.                 int bufSize, Address buffer, Time *timePtr));
  111. static void        DgramSendDone _ARGS_((Dev_HppiSendDSND* dgramCmdPtr));
  112. static void        NetHppiRecvDgram _ARGS_((Net_Interface *interPtr));
  113. static void        DgramRecvDone _ARGS_((Dev_HppiSendDRCV* dgramCmdPtr));
  114. static void        SourceDone _ARGS_((Net_Interface *interPtr, 
  115.                 NetUltraXRBInfo *infoPtr));
  116. static ReturnStatus    NetHppiSource _ARGS_((Net_Interface *interPtr,
  117.                 Net_Address *netAddressPtr, int count,
  118.                 int bufSize, Address buffer, Time *timePtr));
  119. static void        NetHppiResetCallback _ARGS_((ClientData data,
  120.                 Proc_CallInfo *infoPtr));
  121. static void        NetHppiMsgCallback _ARGS_((ClientData data,
  122.                     Proc_CallInfo *infoPtr));
  123. static void        NetHppiCmdCallback _ARGS_((ClientData data,
  124.                            Proc_CallInfo *infoPtr));
  125. static ReturnStatus    NetHppiSetupBoard _ARGS_((NetHppiState *interPtr));
  126. static ReturnStatus    NetHppiStart _ARGS_((NetHppiState *statePtr));
  127. static ReturnStatus    NetHppiStop _ARGS_((NetHppiState *statePtr));
  128. static ReturnStatus    NetHppiSendReq _ARGS_((NetHppiState *statePtr,
  129.                 void (*doneProc)(), ClientData data,
  130.                 Boolean rpc, int scatterLength,
  131.                 Net_ScatterGather *scatterPtr,
  132.                 int requestSize, NetUltraRequest *requestPtr));
  133. static ReturnStatus    NetHppiSendCmd _ARGS_((NetHppiState *statePtr,
  134.                            int size, Address cmdPtr,
  135.                            int flags));
  136. static void        NetHppiConnectionAccepted _ARGS_((Dev_HppiSendALSN*
  137.                               connBlockPtr));
  138. static void        NetHppiXferCallback _ARGS_((Dev_HppiSendXfer* cmdPtr));
  139. static void        NetHppiOpenCallback _ARGS_((Dev_HppiSendOPEN* cmdPtr));
  140. static void        NetHppiConnectionCleanup _ARGS_((Dev_HppiSendRLSE*
  141.                              cmdPtr));
  142. static NetHppiOutputStub _ARGS_((Net_Interface* interPtr, Address hdrPtr,
  143.                  Net_ScatterGather* scatterGatherPtr,
  144.                  int scatterGatherLength, Boolean rpc,
  145.                  ReturnStatus* statusPtr));
  146. static void iocConnCallback _ARGS_ ((Net_HppiConnection* connPtr));
  147. static void iocXferCallback _ARGS_ ((Net_HppiDataRequest* dataReqPtr));
  148. /*
  149.  * Macros for mapping between kernel, DVMA and VME addresses.
  150.  */
  151.  
  152. #define    DVMA_TO_BUFFER(addr, statePtr)         \
  153.     ((Address) (((((unsigned int) (addr)) -     \
  154.     ((unsigned int) (statePtr)->buffersDVMA)) + \
  155.     ((int) (statePtr)->buffers))))
  156.  
  157. #define BUFFER_TO_DVMA(addr, statePtr)         \
  158.     ((Address) ((((unsigned int) (addr)) -     \
  159.     ((unsigned int) (statePtr)->buffers)) +     \
  160.     ((unsigned int) (statePtr)->buffersDVMA)))
  161.  
  162. #define DVMA_TO_VME(addr, statePtr)         \
  163.     ((Address) (((unsigned int) (addr)) -     \
  164.     ((unsigned int) VMMACH_DMA_START_ADDR)))
  165.  
  166. #define VME_TO_DVMA(addr, statePtr)         \
  167.     ((Address) ((((unsigned int)(addr)) & 0x00ffffff) +     \
  168.     ((unsigned int) VMMACH_DMA_START_ADDR)))
  169.  
  170. #define BUFFER_TO_VME(addr, statePtr) \
  171.     ((Address) (DVMA_TO_VME(BUFFER_TO_DVMA(addr,statePtr), (statePtr))))
  172.  
  173. #define VME_TO_BUFFER(addr, statePtr) \
  174.     ((Address) (DVMA_TO_BUFFER(VME_TO_DVMA((addr),statePtr),(statePtr))))
  175.  
  176. #define DVMA_ADDRESS(addr, statePtr) \
  177.     ((unsigned int)(addr) < ((unsigned int)VMMACH_DMA_START_ADDR)? FALSE :TRUE)
  178.  
  179.  
  180. /*
  181.  *----------------------------------------------------------------------
  182.  *
  183.  * NetHppiInit --
  184.  *
  185.  *    Initialize the TMC VME boards.
  186.  *
  187.  * Results:
  188.  *    SUCCESS if the TMC cards were found and initialized.
  189.  *    FAILURE otherwise.
  190.  *
  191.  * Side effects:
  192.  *    None.
  193.  *
  194.  *----------------------------------------------------------------------
  195.  */
  196.  
  197. ReturnStatus
  198. NetHppiInit(interPtr)
  199.     Net_Interface    *interPtr;     /* Network interface. */
  200. {
  201.     unsigned int        ctrlAddr;
  202.     ReturnStatus        status = SUCCESS;
  203.     NetHppiState        *statePtr;
  204.     unsigned long        initialTsap = 0x07d00000;
  205.  
  206.     /*
  207.      * First, see if the controller is present.  We will *always* map it
  208.      * in, since we need to map in two different controllers--the HPPI-S
  209.      * and HPPI-D have different addresses.  The controller address
  210.      * specified will be the setting of bits 23:16 on the boards (see
  211.      * their documentation for specifics)
  212.      */
  213.     ctrlAddr = (unsigned int) interPtr->ctrlAddr;
  214.  
  215.     printf ("NetHppiInit: Trying to locate HPPI boards at VME24D32 0x%x.\n",
  216.         ctrlAddr);
  217.     if (numHppiInterfaces == 0) {
  218.     int i;
  219.     for (i = 0; i < NET_HPPI_MAX_INTERFACES; i++) {
  220.         hppiState[i] = NULL;
  221.     }
  222.     } else if (numHppiInterfaces > NET_HPPI_MAX_INTERFACES) {
  223.     printf ("NetHppiInit: too many HPPI interfaces\n");
  224.     status = FAILURE;
  225.     goto initFailed;
  226.     }
  227.     statePtr = (NetHppiState *)malloc (sizeof (NetHppiState));
  228.  
  229.     if (statePtr == NULL) {
  230.     panic ("NetHppiInit: unable to allocate state area\n");
  231.     }
  232.     hppiState[numHppiInterfaces] = statePtr;
  233.  
  234.     /*
  235.      * Map in boards and attempt to reset them.  If the reset fails, then
  236.      * the boards probably aren't actually there.  NOTE:  the last
  237.      * parameter to VmMach_MapInDevice is the address space.  3 corresponds
  238.      * to VME A24D32.
  239.      */
  240.     statePtr->hppisReg = (NetHppiSrcReg *)
  241.     VmMach_MapInDevice((Address) (ctrlAddr + NET_HPPI_SRC_CTRL_OFFSET), 3);
  242.     statePtr->hppidReg = (NetHppiDestReg *)
  243.     VmMach_MapInDevice((Address) (ctrlAddr + NET_HPPI_DST_CTRL_OFFSET), 3);
  244.     statePtr->iopReg = (NetHppiIopReg *)
  245.     VmMach_MapInDevice((Address) (ctrlAddr + NET_HPPI_IOP_CTRL_OFFSET), 3);
  246.  
  247.     if ((statePtr->hppidReg == NULL) || (statePtr->hppisReg == NULL)) {
  248.     printf ("NetHppiInit: Unable to get map space for boards.\n");
  249.     status = FAILURE;
  250.     goto initFailed;
  251.     } else {
  252.     printf ("NetHppiInit: SRC at virtual 0x%x; DST at virtual 0x%x \n",
  253.         statePtr->hppisReg, statePtr->hppidReg);
  254.     }
  255.  
  256.     /*
  257.      * Reset both boards...
  258.      */
  259.     statePtr->magic = NET_HPPI_STATE_MAGIC;
  260.     statePtr->interPtr = interPtr;
  261.     interPtr->interfaceData = (ClientData) statePtr;
  262.     statePtr->tracePtr = statePtr->traceBuffer;
  263.     statePtr->traceSequence = 0;
  264.     statePtr->queuesInit = FALSE;
  265.     statePtr->priority = NET_HPPI_INTERRUPT_PRIORITY;
  266.     statePtr->requestLevel = NET_HPPI_VME_REQUEST_LEVEL;
  267.     statePtr->addressSpace = NET_HPPI_VME_ADDRESS_SPACE;
  268.     statePtr->hppiNum = numHppiInterfaces;
  269.     statePtr->boardFlags = 0;
  270.     bcopy (&initialTsap, statePtr->curTsap, sizeof (statePtr->curTsap));
  271.     Mach_SetHandler (interPtr->vector, Net_Intr, (ClientData) interPtr);
  272.     interPtr->init     = NetHppiInit;
  273.     interPtr->intr    = NetHppiIntr;
  274.     interPtr->ioctl    = NetHppiIOControl;
  275.     interPtr->reset     = Net_HppiReset;
  276.     interPtr->output     = NetHppiOutputStub;
  277.     interPtr->netType    = NET_NETWORK_ULTRA;
  278.     interPtr->maxBytes    = NET_HPPI_MAX_BYTES;
  279.     interPtr->minBytes    = NET_HPPI_MIN_BYTES;
  280.     interPtr->ctrlAddr = (Address) ctrlAddr;
  281.     status = NetHppiHardReset (interPtr);
  282.     if (status != SUCCESS) {
  283.     printf ("NetHppiInit: board reset failed (boards not present?)\n");
  284.     goto initFailed;
  285.     }
  286. #if 0
  287.     status = NetHppiInfo (statePtr);
  288.     if (status == SUCCESS) {
  289.     printf ("Hppi boards successfully got info.\n");
  290.     } else {
  291.     printf ("NetHppiInit: unable to get info from board.\n");
  292.     status = FAILURE;
  293.     goto initFailed;
  294.     }
  295. #endif
  296.  
  297.  
  298.   initFailed:
  299.     numHppiInterfaces += 1;
  300.     return status;
  301. }
  302.  
  303. /*
  304.  *----------------------------------------------------------------------
  305.  *
  306.  * NetHppiHardReset --
  307.  *
  308.  *    Does a hard reset of the Ultranet adapter. This means the adapter
  309.  *    board goes back to its state right after power-up -- no 
  310.  *    micro-code or anything.
  311.  *
  312.  * Results:
  313.  *    SUCCESS if a reply was received properly, FAILURE otherwise
  314.  *
  315.  * Side effects:
  316.  *    The ultranet adapter is initialized.
  317.  *
  318.  *----------------------------------------------------------------------
  319.  */
  320.  
  321. ReturnStatus
  322. NetHppiHardReset(interPtr)
  323.     Net_Interface    *interPtr;    /* Interface to reset. */
  324. {
  325.     NetHppiState    *statePtr;    /* State of the adapter. */
  326.     ReturnStatus    status = SUCCESS;
  327.     int            resetVal;
  328.     int            srcStatus = SUCCESS, dstStatus = SUCCESS;
  329.  
  330.     if (netHppiDebug) {
  331.     printf ("NetHppiHardReset: entering....\n");
  332.     }
  333.     resetVal = NET_HPPI_RESET_BOARD | NET_HPPI_RESET_CPU;
  334.     statePtr = (NetHppiState *) interPtr->interfaceData;
  335.     printf("Hppi: hard reset boards.\n");
  336.  
  337.     srcStatus = Mach_Probe(sizeof(int), (char *) &resetVal,
  338.         (char *) &(statePtr->hppisReg->reset));
  339.  
  340.     dstStatus = Mach_Probe(sizeof(int), (char *) &resetVal,
  341.         (char *) &(statePtr->hppidReg->reset));
  342.  
  343.     if (srcStatus != SUCCESS) {
  344.     /*
  345.      * Board is no longer responding.
  346.      */
  347.     printf("NetHppiHardReset: HPPI-S did not respond to reset!! 0x%x\n",
  348.            srcStatus);
  349.     statePtr->flags = 0;
  350.     status = FAILURE;
  351.     }
  352.  
  353.     if (dstStatus != SUCCESS) {
  354.     /*
  355.      * Board is no longer responding.
  356.      */
  357.     printf("NetHppiHardReset: HPPI-D did not respond to reset!! 0x%x\n",
  358.            dstStatus);
  359.     statePtr->flags = 0;
  360.     status = FAILURE;
  361.     }
  362.  
  363.     if (status != SUCCESS) {
  364.     return status;
  365.     }
  366.  
  367.     MACH_DELAY(NET_HPPI_RESET_DELAY);
  368.  
  369.     statePtr->hppisReg->reset = 0;
  370.     statePtr->hppidReg->reset = 0;
  371.     statePtr->hppisReg->config = NET_HPPI_SRC_CONFIG_VALUE;
  372.     statePtr->hppidReg->config = NET_HPPI_DST_CONFIG_VALUE;
  373.     statePtr->outputCallback = NULL;
  374.     InitQueues(statePtr);
  375.     /*
  376.      * After a reset the adapter is in the EPROM mode.
  377.      * This allows several additional commands (load, go, etc.) to be
  378.      * sent to the adapter.
  379.      */
  380.     statePtr->flags = (NET_HPPI_STATE_EXIST | NET_HPPI_STATE_SRC_EPROM |
  381.                NET_HPPI_STATE_DST_EPROM);
  382.  
  383.     if (netHppiDebug) {
  384.     printf ("NetHppiHardReset: exiting....\n");
  385.     }
  386.  
  387.     return status;
  388. }
  389.  
  390. /*
  391.  *----------------------------------------------------------------------
  392.  *
  393.  * NetHppiReset --
  394.  *
  395.  *    Resets the board by sending it a stop command followed by a
  396.  *    start command.  The XRB queues are also initialized.
  397.  *    Assumes the interface mutex is held.
  398.  *
  399.  * Results:
  400.  *    A standard Sprite return status.
  401.  *
  402.  * Side effects:
  403.  *    None.
  404.  *
  405.  *----------------------------------------------------------------------
  406.  */
  407.  
  408. ReturnStatus
  409. NetHppiReset(interPtr)
  410.     Net_Interface    *interPtr;    /* Interface to reset. */
  411. {
  412.     ReturnStatus    status = SUCCESS;
  413.     NetHppiState    *statePtr;    /* State of the adapter. */
  414.     Dev_HppiReset    resetCmd;    /* reset command for both src & dst */
  415.     int which = 0;            /* reset SRC, DST, or both */
  416.  
  417.     statePtr = (NetHppiState *) interPtr->interfaceData;
  418.     if (which == 0) {
  419.     which = NET_HPPI_SRC_CMD | NET_HPPI_DST_CMD;
  420.     }
  421.     if (netHppiDebug) {
  422.     if (which & NET_HPPI_SRC_CMD) {
  423.         printf ("NetHppiReset: resetting SRC board.\n");
  424.     }
  425.     if (which & NET_HPPI_DST_CMD) {
  426.         printf ("NetHppiReset: resetting DST board.\n");
  427.     }
  428.     }
  429.  
  430.     resetCmd.hdr.opcode = DEV_HPPI_RESET;
  431.     if (which & NET_HPPI_SRC_CMD) {
  432.     resetCmd.hdr.magic = DEV_HPPI_SRC_MAGIC;
  433.     status = NetHppiSendCmd (statePtr, sizeof (resetCmd),
  434.                  (Address)&resetCmd, NET_HPPI_SRC_CMD);
  435.     if (status != SUCCESS) {
  436.         printf ("NetHppiReset: soft reset of SRC board failed.\n");
  437.         return (status);
  438.     }
  439.     }
  440.  
  441.     if (which & NET_HPPI_DST_CMD) {
  442.     resetCmd.hdr.magic = DEV_HPPI_DEST_MAGIC;
  443.     status = NetHppiSendCmd (statePtr, sizeof (resetCmd),
  444.                  (Address)&resetCmd, 0);
  445.     if (status != SUCCESS) {
  446.         printf ("NetHppiReset: soft reset of DST board failed.\n");
  447.     }
  448.     }
  449.  
  450.     InitQueues(statePtr);
  451.  
  452.     statePtr->flags = NET_HPPI_STATE_EXIST;
  453.  
  454.     if (which & NET_HPPI_RESET_RESTART) {
  455.     status = NetHppiSetupBoard (statePtr);
  456.  
  457.     status = NetHppiStop(statePtr);
  458.     if (status != NULL) {
  459.         printf("NetHppiReset: stop failed\n");
  460.         return status;
  461.     }
  462.  
  463.     status = NetHppiStart(statePtr);
  464.     if (status != NULL) {
  465.         printf("NetHppiReset: start failed\n");
  466.         return status;
  467.     }
  468.     }
  469.     if (netHppiDebug) {
  470.     printf ("NetHppiReset: reset done...returning.\n");
  471.     }
  472.  
  473.     return (status);
  474. }
  475.  
  476. /*----------------------------------------------------------------------
  477.  *
  478.  * Net_HppiReset --
  479.  *
  480.  *    Reset the HPPI boards.  This can be called
  481.  *     from outside the module since it locks the mutex.
  482.  *
  483.  * Results:
  484.  *
  485.  * Side effects:
  486.  *    None.
  487.  *
  488.  *----------------------------------------------------------------------
  489.  */
  490.  
  491. void
  492. Net_HppiReset(interPtr)
  493.     Net_Interface    *interPtr;    /* Interface to reset. */
  494. {
  495.     MASTER_LOCK(&interPtr->mutex);
  496.     /*
  497.      * If we are at interrupt level we have to do a callback to reset
  498.      * the adapter since we can't wait for the response from
  499.      * the adapter (there may not be a current process and we can't
  500.      * get the interrupt).
  501.      */
  502.     if (Mach_AtInterruptLevel()) {
  503.     Proc_CallFunc(NetHppiResetCallback, (ClientData) interPtr, 0);
  504.     } else {
  505.     (void) NetHppiReset(interPtr);
  506.     }
  507.     MASTER_UNLOCK(&interPtr->mutex);
  508. }
  509.  
  510. /*
  511.  *----------------------------------------------------------------------
  512.  *
  513.  * NetHppiResetCallback --
  514.  *
  515.  *    This routine is called by the Proc_ServerProc during the
  516.  *    callback to reset the adapter.
  517.  *
  518.  * Results:
  519.  *    None.
  520.  *
  521.  * Side effects:
  522.  *    The adapter is reset.
  523.  *
  524.  *----------------------------------------------------------------------
  525.  */
  526.  
  527. static void
  528. NetHppiResetCallback(data, infoPtr)
  529.     ClientData        data;        /* Ptr to the interface to reset. */
  530.     Proc_CallInfo    *infoPtr;    /* Unused. */
  531. {
  532.     Net_HppiReset((Net_Interface *) data);
  533. }
  534.  
  535.  
  536. /*
  537.  *----------------------------------------------------------------------
  538.  *
  539.  * Net_HppiHardReset --
  540.  *
  541.  *    This is a version of the hard reset routine that can be called from
  542.  *     outside the net module because it does not assume that a
  543.  *    lock is held (or interrupts are disabled) when it is called.
  544.  *
  545.  * Results:
  546.  *    None.
  547.  *
  548.  * Side effects:
  549.  *    The adapter is reset.
  550.  *
  551.  *----------------------------------------------------------------------
  552.  */
  553.  
  554. void
  555. Net_HppiHardReset(interPtr)
  556.     Net_Interface    *interPtr;    /* Interface to reset. */
  557. {
  558.     MASTER_LOCK(&interPtr->mutex);
  559.  
  560.     NetHppiHardReset(interPtr);
  561.  
  562.     MASTER_UNLOCK(&interPtr->mutex);
  563. }
  564.  
  565.  
  566. /*
  567.  *----------------------------------------------------------------------
  568.  *
  569.  * getSgTag --
  570.  *
  571.  *    Get a free tag for the scatter-gather array.  This assumes that
  572.  *    the mutex is held by the calling routine.
  573.  *
  574.  * Results:
  575.  *    The tag to use (or -1 if none available).
  576.  * Side effects:
  577.  *    A tag is allocated.
  578.  *
  579.  *----------------------------------------------------------------------
  580.  */
  581. static
  582. int
  583. getSgTag (statePtr)
  584. NetHppiState*    statePtr;
  585. {
  586.     int        i;
  587.     int        curTag;
  588.  
  589.     for (i = 0, curTag = statePtr->curSgTag; statePtr->tags[curTag] != 0;
  590.      curTag ++, i++) {
  591.     if (curTag == NET_HPPI_MAX_TAGS) {
  592.         curTag = 1;
  593.     }
  594.     if (i == NET_HPPI_MAX_TAGS - 1) {
  595.         printf ("getSgTag: no free tags!\n");
  596.         return (-1);
  597.     }
  598.     }
  599.     statePtr->curSgTag = curTag;
  600.     statePtr->tags[curTag] = 1;
  601.  
  602.     return (curTag);
  603. }
  604.  
  605. static
  606. void
  607. freeSgTag (statePtr, tag)
  608. NetHppiState*    statePtr;
  609. char        tag;
  610. {
  611.     if (netHppiDebug) {
  612.     printf ("freeing hppi tag %d\n", tag);
  613.     }
  614.     statePtr->tags[tag] = 0;
  615. }
  616.  
  617. /*
  618.  *----------------------------------------------------------------------
  619.  *
  620.  * NetHppiCopyFromFifo --
  621.  *
  622.  *    Copy a command to the appropriate FIFO (its address is passed).
  623.  *    This is similar to bcopy, except all the words in the source
  624.  *    address are copied to the (single) address corresponding to
  625.  *    a HPPI board FIFO.
  626.  *
  627.  * Results:
  628.  *    SUCCESS if the adapter responded to the command,
  629.  *    DEV_TIMEOUT if the adapter did not respond
  630.  *
  631.  * Side effects:
  632.  *    The data is copied to the appropriate FIFO.
  633.  *
  634.  *----------------------------------------------------------------------
  635.  */
  636. static
  637. ReturnStatus
  638. NetHppiCopyFromFifo (addr, size, statePtr, which)
  639.     uint32    *addr;        /* the command to be sent */
  640.     int        size;        /* size of the command (in bytes) */
  641.     NetHppiState *statePtr;
  642.     int        which;        /* copy from SRC or dst fifo? */
  643. {
  644.     volatile uint32 *fifoAddr;    /* address of the FIFO to copy to */
  645.     volatile uint32 *stateAddr;    /* address of state register */
  646.     register uint32 *kaddr = addr;
  647.     ReturnStatus status = SUCCESS;
  648.     int i;
  649.  
  650.     if (which == NET_HPPI_SRC_CMD) {
  651.     stateAddr = &(statePtr->hppisReg->status);
  652.     fifoAddr = &(statePtr->hppisReg->outputFifo);
  653.     } else {
  654.     stateAddr = &(statePtr->hppidReg->status);
  655.     fifoAddr = &(statePtr->hppidReg->outputFifo);
  656.     }
  657.  
  658.     if (netHppiDebug) {
  659.     printf ("NetHppiCopyFromFifo: trying to copy %d bytes from fifo.\n",
  660.         size);
  661.     }
  662.     for (i = 0; i < size; i += 4) {
  663.     WAIT_FOR_BIT_CLEAR (stateAddr, NET_HPPI_DELAY, DEV_HPPI_OFIFO_EMPTY);
  664.     if ((*stateAddr) & DEV_HPPI_OFIFO_EMPTY) {
  665.         if (netHppiDebug) {
  666.         printf ("\nNetHppiCopyFromFifo: copy timed out.\n");
  667.         }
  668.         return (DEV_TIMEOUT);
  669.     }
  670.     *addr = *fifoAddr;
  671.     if (netHppiDebug) {
  672.         printf ("0x%08x ", *addr);
  673.         if ((i % 32) == 31) {
  674.         printf ("\n");
  675.         }
  676.     }
  677.     addr++;
  678.     }
  679.  
  680.     if (netHppiDebug) {
  681.     printf ("\nNetHppiCopyFromFifo: copied %d bytes from fifo to 0x%x\n",
  682.         size, kaddr);
  683.     }
  684.     return (status);
  685. }
  686.  
  687. /*
  688.  *----------------------------------------------------------------------
  689.  *
  690.  * NetHppiCopyToFifo --
  691.  *
  692.  *    Copy a command to the appropriate FIFO (its address is passed).
  693.  *    This is similar to bcopy, except all the words in the source
  694.  *    address are copied to the (single) address corresponding to
  695.  *    a HPPI board FIFO.
  696.  *
  697.  * Results:
  698.  *    SUCCESS if the adapter responded to the command,
  699.  *    DEV_TIMEOUT if the adapter did not respond
  700.  *
  701.  * Side effects:
  702.  *    The data is copied to the appropriate FIFO.
  703.  *
  704.  *----------------------------------------------------------------------
  705.  */
  706. static
  707. ReturnStatus
  708. NetHppiCopyToFifo (addr, size, statePtr, which)
  709.     uint32    *addr;        /* the command to be sent */
  710.     int        size;        /* size of the command (in bytes) */
  711.     NetHppiState *statePtr;    /* ptr to HPPI state */
  712.     int        which;        /* copy to src or dest fifo? */
  713. {
  714.     volatile uint32 *fifoAddr;    /* address of the FIFO to copy to */
  715.     volatile uint32 *stateAddr;    /* address of state register */
  716.     register uint32 *kaddr = addr;
  717.     register int cnt, xferCnt, i;
  718.     ReturnStatus status = SUCCESS;
  719.  
  720.     if (which == NET_HPPI_SRC_CMD) {
  721.     stateAddr = &(statePtr->hppisReg->status);
  722.     fifoAddr = &(statePtr->hppisReg->inputFifo);
  723.     } else {
  724.     stateAddr = &(statePtr->hppidReg->status);
  725.     fifoAddr = &(statePtr->hppidReg->inputFifo);
  726.     }
  727.  
  728.     cnt = size;
  729.     while (cnt > 0) {
  730.     xferCnt = (cnt > (DEV_HPPI_IFIFO_DEPTH/2 - 16)) ?
  731.            (DEV_HPPI_IFIFO_DEPTH/2 - 16) : cnt;
  732.     for (i = 0; i < xferCnt; i += 4, cnt -= 4) {
  733.         *fifoAddr = *(addr++);
  734.     }
  735.     if (cnt > 0) {
  736.         WAIT_FOR_BIT_CLEAR (stateAddr, NET_HPPI_DELAY, DEV_HPPI_IFIFO_HF);
  737.         if ((*stateAddr) & DEV_HPPI_IFIFO_HF) {
  738. #ifndef CLEAN
  739.         if (netHppiDebug) {
  740.             printf ("NetHppiCopyToFifo: timeout after %d bytes\n",
  741.                 size - i);
  742.         }
  743. #endif
  744.         return (DEV_TIMEOUT);
  745.         }
  746.     }
  747.     }
  748.  
  749.     if (netHppiDebug) {
  750.     printf ("NetHppiCopyToFifo: copied %d bytes from 0x%x to fifo\n",
  751.         size, kaddr);
  752.     }
  753.     return (status);
  754. }
  755.  
  756. /*
  757.  *----------------------------------------------------------------------
  758.  *
  759.  * NetHppiReleaseSrcFifo
  760.  *
  761.  *    Release the HPPI-S command FIFO.  It must have been previously
  762.  *    acquired by NetHppiAcquireSrcFifo.
  763.  *
  764.  * Results:
  765.  *    SUCCESS if the adapter responded to the command,
  766.  *
  767.  * Side effects:
  768.  *    The server releases control of the HPPI-S command FIFO.
  769.  *
  770.  *----------------------------------------------------------------------
  771.  */
  772. static
  773. ReturnStatus
  774. NetHppiReleaseSrcFifo (statePtr)
  775.     NetHppiState    *statePtr;    /* state of the adapter */
  776. {
  777.     ReturnStatus status = SUCCESS;
  778.  
  779.     if (!(statePtr->flags & NET_HPPI_OWN_SRC_FIFO)) {
  780.     printf ("NetHppiReleaseSrcFifo: don't own SRC FIFO.\n");
  781.     }
  782.  
  783. #if 0
  784.     statePtr->hppidReg->commandData = 0x0;
  785.     statePtr->flags &= ~NET_HPPI_OWN_SRC_FIFO;
  786. #endif
  787.  
  788.     return (status);
  789. }
  790.  
  791. /*
  792.  *----------------------------------------------------------------------
  793.  *
  794.  * NetHppiAcquireSrcFifo
  795.  *
  796.  *    Arbitrate with the HPPI-D board to get access to the HPPI-S
  797.  *    FIFO.  This is done so the HPPI-D and the server don't
  798.  *    interleave requests in the HPPI-S command FIFO.
  799.  *
  800.  * Results:
  801.  *    SUCCESS if the adapter responded to the command,
  802.  *    DEV_TIMEOUT if the adapter did not respond within a specified time.
  803.  *
  804.  * Side effects:
  805.  *    The server gets control of the HPPI-S command FIFO.
  806.  *
  807.  *----------------------------------------------------------------------
  808.  */
  809. static
  810. ReturnStatus
  811. NetHppiAcquireSrcFifo (statePtr, timeOutVal)
  812.     NetHppiState    *statePtr;    /* state of the adapter */
  813.     int            timeOutVal;    /* maximum time to wait */
  814. {
  815.     ReturnStatus status = SUCCESS;
  816. #if 0
  817.     volatile NetHppiDestReg *destReg = statePtr->hppidReg;
  818. #endif
  819.  
  820. #if 0
  821.     /*
  822.      * Notify the HPPI-D that we want to talk to the HPPI-S.
  823.      */
  824.     destReg->commandData = 0x10000;
  825.     destReg->command |= 0x1000000;
  826.  
  827.     /*
  828.      * Wait for the HPPI-D to grant our request;
  829.      */
  830.     while (!((destReg->responseData == 0x0) &&
  831.          (!(destReg->command & 0xff000000)) &&
  832.        (timeOutVal > 0)) {
  833.     timeOutVal -= 1;
  834.     }
  835. #endif
  836.  
  837.     statePtr->flags |= NET_HPPI_OWN_SRC_FIFO;
  838.  
  839.     if (timeOutVal == 0) {
  840.     status = NetHppiReleaseSrcFifo (statePtr);
  841.     if (status != SUCCESS) {
  842.         panic ("NetHppiAcquireSrcFifo: timeout and FIFO release failed.\n");
  843.     }
  844.     status = DEV_TIMEOUT;
  845.     }
  846.  
  847.     return (status);
  848. }
  849.  
  850. /*------------------------------------------------------------
  851.  *
  852.  * getFreeBuffer
  853.  *
  854.  *    This routine removes a buffer from the list of free buffers.
  855.  *
  856.  *------------------------------------------------------------
  857.  */
  858. static
  859. Address
  860. getFreeBuffer (statePtr)
  861.     NetHppiState *statePtr;
  862. {
  863.     List_Links *itemPtr;
  864.     int        signal;
  865.  
  866.     while(List_IsEmpty(statePtr->freeBufferList)) {
  867.     statePtr->bufferAvail.waiting = TRUE;
  868.     signal = Sync_SlowMasterWait((unsigned int) &statePtr->bufferAvail,
  869.                      &(statePtr->interPtr->mutex), TRUE);
  870.     if (signal) {
  871.         return ((Address)NIL);
  872.     }
  873.     }
  874.     itemPtr = List_First(statePtr->freeBufferList);
  875.     if (itemPtr == statePtr->freeBufferList) {
  876.     panic("NetHppi: getFreeBuffer list screwup\n");
  877.     }
  878.     List_Remove(itemPtr);
  879.     
  880.     return ((Address)itemPtr);
  881. }
  882.  
  883. /*
  884.  *----------------------------------------------------------------------
  885.  *
  886.  * NetHppiSendCmd --
  887.  *
  888.  *    Send a command to the adapter.
  889.  *
  890.  * Results:
  891.  *    SUCCESS if the adapter responded to the command,
  892.  *    DEV_TIMEOUT if the adapter did not respond
  893.  *
  894.  * Side effects:
  895.  *    A command is sent to the adapter.
  896.  *
  897.  *----------------------------------------------------------------------
  898.  */
  899.  
  900. ReturnStatus
  901. NetHppiSendCmd(statePtr, size, cmdPtr, flags)
  902.     NetHppiState    *statePtr;    /* State of the adapter. */
  903.     int            size;        /* Size of command block. */
  904.     Address        cmdPtr;        /* The command block. */
  905.     int            flags;        /* flags pertaining to this command */
  906. {
  907.     ReturnStatus    status = SUCCESS;
  908.     Dev_HppiCmdHdr    *cmdHdr = (Dev_HppiCmdHdr *)cmdPtr;
  909.  
  910.     /*
  911.      * We must copy the command to the adapter ourselves, so there's
  912.      * no point in mapping the command into DMA memory.  If the command
  913.      * goes to the destination, we just copy the command into the
  914.      * destination's FIFO.  If it goes into the source, we must
  915.      * arbitrate for control of the FIFO.  We can't wait for results
  916.      * since incoming packet information could arrive first.
  917.      */
  918.     if (netHppiDebug) {
  919.     printf("NetHppiSendCmd: sending command %d to adapter\n",
  920.         cmdHdr->opcode);
  921.     printf("NetHppiSendCmd: size = %d, cmdPtr = 0x%x\n", size, cmdPtr);
  922.     }
  923.     if ((int) cmdPtr & 0x3) {
  924.     panic("NetHppiSendCmd: command not aligned on a word boundary\n");
  925.     }
  926.  
  927.     if (flags & NET_HPPI_SRC_CMD) {
  928.     if (flags & NET_HPPI_STATE_SRC_EPROM) {
  929.         printf ("NetHppiSendCmd: SRC not running\n");
  930.         status = FAILURE;
  931.         goto exit;
  932.     }
  933.     cmdHdr->magic = DEV_HPPI_SRC_MAGIC;
  934.     if (!(statePtr->flags & NET_HPPI_OWN_SRC_FIFO)) {
  935.         status = NetHppiAcquireSrcFifo (statePtr, 1000000);
  936.     }
  937.     if (status == SUCCESS) {
  938.         status = NetHppiCopyToFifo (cmdPtr, size, statePtr,
  939.                     NET_HPPI_SRC_CMD);
  940.     }
  941.     if (!(flags & NET_HPPI_KEEP_SRC_FIFO)) {
  942.         NetHppiReleaseSrcFifo (statePtr);
  943.     }
  944.     } else {
  945.     if (flags & NET_HPPI_STATE_DST_EPROM) {
  946.         printf ("NetHppiSendCmd: DST not running\n");
  947.         status = FAILURE;
  948.         goto exit;
  949.     }
  950.     cmdHdr->magic = DEV_HPPI_DEST_MAGIC;
  951.     status = NetHppiCopyToFifo (cmdPtr, size, statePtr, 0);
  952.     }
  953.  
  954.     if (netHppiDebug) {
  955.     printf ("NetHppiSendCmd: command sent (status = %d).\n", status);
  956.     }
  957.  
  958. exit:
  959.     return (status);
  960. }
  961.  
  962. /*
  963.  *----------------------------------------------------------------------
  964.  *
  965.  * NetHppiMsgCallback
  966.  *
  967.  *    This is the routine called back by a ServerProc to handle a
  968.  *    message from the HPPI boards.  The message can be one of three
  969.  *    types: an error message from either HPPI-S or HPPI-D, or a
  970.  *    request from the HPPI-D to send data to the HPPI-S.
  971.  *
  972.  * Results:
  973.  *    None.
  974.  *
  975.  * Side effects:
  976.  *    The message is retrieved from the HPPI board(s) and appropriate
  977.  *    actions are taken.
  978.  *
  979.  *----------------------------------------------------------------------
  980.  */
  981. static
  982. void
  983. NetHppiMsgCallback (data, infoPtr)
  984.     ClientData        data;
  985.     Proc_CallInfo    *infoPtr;
  986. {
  987.     Net_Interface    *interPtr = (Net_Interface *)data;
  988.     NetHppiState    *statePtr = (NetHppiState *)interPtr->interfaceData;
  989.     Dev_HppiErrorMsg    errMsg;
  990.     int            size;
  991.     int            numElements;
  992.     int            i;
  993.     int            status = SUCCESS;
  994.  
  995.     if (netHppiDebug) {
  996.     printf ("NetHppiMsgCallback: entering with data = 0x%x\n", data);
  997.     }
  998.     if (!(statePtr->flags &
  999.       (NET_HPPI_STATE_SRC_ERROR | NET_HPPI_STATE_DST_ERROR))) {
  1000.     Dev_HppiCopyDataMsg    copyDataMsg;
  1001.     Dev_HppiOutput        outputCmd;
  1002.  
  1003.     size = sizeof (copyDataMsg.size) + sizeof (copyDataMsg.magic) +
  1004.         sizeof (copyDataMsg.dmaWord);
  1005.  
  1006.     /*
  1007.      * Copy the entire message from the destination board.  Since
  1008.      * we can only get one type of message, we don't need to check
  1009.      * message type except for verification.
  1010.      */
  1011.     NetHppiCopyFromFifo (©DataMsg, size, statePtr, 0);
  1012.     if (copyDataMsg.magic != DEV_HPPI_COPY_MAGIC) {
  1013.         printf ("NetHppiMsgCallback: bad copyToSource magic number\n");
  1014.         goto exit;
  1015.     }
  1016.     NetHppiCopyFromFifo (&(copyDataMsg.element[0]), copyDataMsg.size,
  1017.                  statePtr, 0);
  1018.     if (netHppiTrace) {
  1019.         outputCmd.hdr.opcode = DEV_HPPI_OUTPUT_TRACE;
  1020.     } else {
  1021.         outputCmd.hdr.opcode = DEV_HPPI_OUTPUT;
  1022.     }
  1023.  
  1024.     numElements = copyDataMsg.size / sizeof (copyDataMsg.element[0]);
  1025.     for (i = 0, size = sizeof (copyDataMsg.dmaWord);
  1026.          i < numElements; i++) {
  1027.         size += copyDataMsg.element[i].size;
  1028.     }
  1029.     copyDataMsg.dmaWord.cmd &= ~NET_ULTRA_DMA_CMD_FROM_ADAPTER;
  1030.     copyDataMsg.dmaWord.cmd |= NET_ULTRA_DMA_CMD_DMA_DATA;
  1031.     outputCmd.hdr.magic = DEV_HPPI_SRC_MAGIC;
  1032.     outputCmd.fifoDataSize = size;
  1033.     outputCmd.iopDataSize = 0;
  1034.     NetHppiSendCmd (statePtr, sizeof (outputCmd), (Address)&outputCmd,
  1035.             NET_HPPI_SRC_CMD | NET_HPPI_KEEP_SRC_FIFO);
  1036.     NetHppiCopyToFifo (&(copyDataMsg.dmaWord),
  1037.                sizeof (copyDataMsg.dmaWord), statePtr,
  1038.                NET_HPPI_SRC_CMD);
  1039.     /*
  1040.      * Copy scatter-gather buffers to input FIFO.
  1041.      */
  1042.     for (i = 0; i < numElements; i++) {
  1043.         NetHppiCopyToFifo (VME_TO_BUFFER (copyDataMsg.element[i].address,
  1044.                           statePtr),
  1045.                    copyDataMsg.element[i].size, statePtr,
  1046.                    NET_HPPI_SRC_CMD);
  1047.     }
  1048.     NetHppiReleaseSrcFifo (statePtr);
  1049.     } else {
  1050.     if (statePtr->flags & NET_HPPI_STATE_SRC_ERROR) {
  1051.         status = NetHppiCopyFromFifo (&errMsg, sizeof (errMsg),
  1052.                       statePtr, NET_HPPI_SRC_CMD);
  1053.         if (errMsg.magic != DEV_HPPI_ERR_MAGIC) {
  1054.         printf ("NetHppiMsgCallback: bad SRC error magic number\n");
  1055.         goto exit;
  1056.         }
  1057.         if (netHppiDebug) {
  1058.         printf ("NetHppiMsgCallback: SRC error (%d words)\n",
  1059.             errMsg.errorInfoLength);
  1060.         }
  1061.         status = NetHppiCopyFromFifo (&(statePtr->srcErrorBuffer),
  1062.                       (errMsg.errorInfoLength << 2),
  1063.                       statePtr, NET_HPPI_SRC_CMD);
  1064.     }
  1065.  
  1066.     if (statePtr->flags & NET_HPPI_STATE_DST_ERROR) {
  1067.         status = NetHppiCopyFromFifo (&errMsg, sizeof (errMsg), statePtr,
  1068.                       NET_HPPI_SRC_CMD);
  1069.         if (errMsg.magic != DEV_HPPI_ERR_MAGIC) {
  1070.         printf ("NetHppiMsgCallback: bad DST error magic number\n");
  1071.         goto exit;
  1072.         }
  1073.         if (netHppiDebug) {
  1074.         printf ("NetHppiMsgCallback: DST error (%d words)\n",
  1075.             errMsg.errorInfoLength);
  1076.         }
  1077.         status = NetHppiCopyFromFifo (&(statePtr->dstErrorBuffer),
  1078.                       (errMsg.errorInfoLength << 2),
  1079.                       statePtr, 0);
  1080.     }
  1081.     }
  1082.  
  1083.   exit:
  1084.     if (status != SUCCESS) {
  1085.     printf ("NetHppiMsgCallback: error 0x%x occurred\n", status);
  1086.     }
  1087.     if (netHppiDebug) {
  1088.     printf ("NetHppiMsgCallback: returning....\n");
  1089.     }
  1090. }
  1091.  
  1092. /*
  1093.  *----------------------------------------------------------------------
  1094.  *
  1095.  * NetHppiLoopback
  1096.  *
  1097.  *    Set up the HIPPI boards for loopback testing.  This can either
  1098.  *    mean a full loopback from xbus to hipppi and back, or a partial
  1099.  *    loop from SRC -> DST -> XBUS.
  1100.  *
  1101.  * Returns:
  1102.  *    none
  1103.  * Side effects:
  1104.  *    Sends commands to the HIPPI boards.
  1105.  *
  1106.  *----------------------------------------------------------------------
  1107.  */
  1108. static
  1109. void
  1110. NetHppiLoopback (statePtr, size, callbackProc, clientData, srcPat)
  1111. NetHppiState*    statePtr;
  1112. int    size;        /* size in BYTES */
  1113. void    (*callbackProc)();
  1114. ClientData clientData;
  1115. int    srcPat;
  1116. {
  1117.     Dev_HppiOutput    outputCmd;
  1118.     Dev_HppiOutputPattern patternCmd;
  1119.  
  1120.     if (statePtr->outputCallback != NULL) {
  1121.     (callbackProc)(clientData, FAILURE);
  1122.     } else {
  1123.     statePtr->outputCallback = callbackProc;
  1124.     statePtr->outputClientData = clientData;
  1125.     outputCmd.fifoDataSize = 0;
  1126.     outputCmd.iopDataSize = size;
  1127.     outputCmd.hdr.opcode = DEV_HPPI_OUTPUT_TO_IOP;
  1128.     NetHppiSendCmd (statePtr, sizeof (outputCmd), (Address)&outputCmd,
  1129.             NET_HPPI_DST_CMD);
  1130.     if (srcPat == 0) {
  1131.         outputCmd.hdr.opcode = DEV_HPPI_OUTPUT;
  1132.         NetHppiSendCmd (statePtr, sizeof (outputCmd), (Address)&outputCmd,
  1133.                 NET_HPPI_SRC_CMD);
  1134.     } else if (srcPat == 1) {
  1135.         patternCmd.hdr.opcode = DEV_HPPI_OUTPUT_PATTERN;
  1136.         patternCmd.size = size;
  1137.         patternCmd.start = 0;
  1138.         patternCmd.increment = 0x00010001;
  1139.         NetHppiSendCmd (statePtr, sizeof (patternCmd),(Address)&patternCmd,
  1140.                 NET_HPPI_SRC_CMD);
  1141.     }
  1142.     }
  1143. }
  1144.  
  1145. static
  1146. void
  1147. iopOutputCallback (statePtr, status)
  1148. NetHppiState*    statePtr;
  1149. ReturnStatus    status;
  1150. {
  1151.     MASTER_LOCK (&(statePtr->interPtr->mutex));
  1152.     if (!(statePtr->flags & NET_HPPI_STATE_IOP_OUTPUT_TEST)) {
  1153.     printf ("Hppi iopOutputCallback: not testing iop?\n");
  1154.     }
  1155.     statePtr->flags &= ~NET_HPPI_STATE_IOP_OUTPUT_TEST;
  1156.     Sync_MasterBroadcast (&iopOutputDone);
  1157.     MASTER_UNLOCK (&(statePtr->interPtr->mutex));
  1158. }
  1159.  
  1160. /*
  1161.  *----------------------------------------------------------------------
  1162.  *
  1163.  * Net_HppiLoopback
  1164.  *
  1165.  *    This routine is intended ONLY for debugging.  It calls NetHppiLoopback
  1166.  *    to send data from IOP bus -> HIPPI-S -> HIPPI-D -> IOP bus.
  1167.  *    The supplied callback routine will be called when the
  1168.  *    transfer completes.  Note that the callback may occur at interrupt
  1169.  *    level.  Also, only one of these transfers may be outstanding at any
  1170.  *    time.  If this is called while there is still an outstanding output
  1171.  *    command, the callback will immediately be called with FAILURE status.
  1172.  *
  1173.  * Returns:
  1174.  *    none
  1175.  * Side effects:
  1176.  *    Commands are sent to the HIPPI-D and HIPPI-S boards.
  1177.  *
  1178.  *----------------------------------------------------------------------
  1179.  */
  1180. void
  1181. Net_HppiLoopback (hippiNum, size, callbackProc, clientData)
  1182. int    hippiNum;
  1183. int    size;        /* size in BYTES */
  1184. void    (*callbackProc)();
  1185. ClientData clientData;
  1186. {
  1187.     NetHppiState*    statePtr;
  1188.  
  1189.     if (netHppiDebug) {
  1190.     printf ("Net_HppiLoopback: called for unit %d.\n", hippiNum);
  1191.     }
  1192.     if ((hippiNum >= NET_HPPI_MAX_INTERFACES) ||
  1193.     (statePtr = hppiState[hippiNum]) == NULL) {
  1194.     (callbackProc)(clientData, DEV_INVALID_UNIT);
  1195.     return;
  1196.     }
  1197.     MASTER_LOCK (&(statePtr->interPtr->mutex));
  1198.     NetHppiLoopback (statePtr, size, callbackProc, clientData, 0);
  1199.     MASTER_UNLOCK (&(statePtr->interPtr->mutex));
  1200. }
  1201.  
  1202. /*
  1203.  *----------------------------------------------------------------------
  1204.  *
  1205.  * Net_HppiSrcPattern
  1206.  *
  1207.  *    This routine is almost identical to Net_HppiLoopback, except
  1208.  *    that the HIPPI source board is set up to provide a fixed
  1209.  *    pattern rather than use data from the IOP bus.
  1210.  *
  1211.  * Returns:
  1212.  *    none
  1213.  * Side effects:
  1214.  *    Sets up HIPPI boards.
  1215.  *
  1216.  *----------------------------------------------------------------------
  1217.  */
  1218. void
  1219. Net_HppiSrcPattern (hippiNum, size, callbackProc, clientData)
  1220. int    hippiNum;
  1221. int    size;        /* size in BYTES */
  1222. void    (*callbackProc)();
  1223. ClientData clientData;
  1224. {
  1225.     NetHppiState*    statePtr;
  1226.  
  1227.     if (netHppiDebug) {
  1228.     printf ("Net_HppiSrcPattern: called for unit %d.\n", hippiNum);
  1229.     }
  1230.     if ((hippiNum >= NET_HPPI_MAX_INTERFACES) ||
  1231.     (statePtr = hppiState[hippiNum]) == NULL) {
  1232.     (callbackProc)(clientData, DEV_INVALID_UNIT);
  1233.     return;
  1234.     }
  1235.     MASTER_LOCK (&(statePtr->interPtr->mutex));
  1236.     NetHppiLoopback (statePtr, size, callbackProc, clientData, 1);
  1237.     MASTER_UNLOCK (&(statePtr->interPtr->mutex));
  1238. }
  1239.  
  1240. /*
  1241.  *----------------------------------------------------------------------
  1242.  *
  1243.  * NetHppiIntr --
  1244.  *
  1245.  *    Handle an interrupt from the HPPI boards.
  1246.  *
  1247.  * Results:
  1248.  *    None.
  1249.  *
  1250.  * Side effects:
  1251.  *    None.
  1252.  *
  1253.  *----------------------------------------------------------------------
  1254.  */
  1255.  
  1256. /*ARGSUSED*/
  1257. void
  1258. NetHppiIntr(interPtr, polling)
  1259.     Net_Interface    *interPtr;    /* Interface to process. */
  1260.     Boolean        polling;    /* TRUE if are being polled instead of
  1261.                      * processing an interrupt. */
  1262. {
  1263.     NetUltraXRB        *xrbPtr;
  1264.     NetUltraXRB        *nextXRBPtr;
  1265.     NetHppiState    *statePtr;
  1266.     volatile NetUltraDMAInfo *dmaPtr;
  1267.     NetUltraRequestHdr  *hdrPtr;
  1268.     NetUltraXRBInfo    *infoPtr;
  1269.     int            processed;
  1270.     NetUltraTraceInfo    *tracePtr;
  1271.     Address        buffer;
  1272.     int            hppiStatus;
  1273.     unsigned int    response;
  1274.  
  1275.     statePtr = (NetHppiState *) interPtr->interfaceData;
  1276.     response = statePtr->hppidReg->responseData;
  1277.     /*
  1278.      * Acknowledge the interrupts by setting(!) the interrupt bits in the
  1279.      * status registers.
  1280.      */
  1281.     statePtr->hppisReg->status = NET_HPPI_SRC_STATUS_INTR;
  1282.     statePtr->hppidReg->status = NET_HPPI_DST_STATUS_INTR;
  1283.     MASTER_LOCK(&interPtr->mutex);
  1284.     if (response == DEV_HPPI_INTR_MAGIC) {
  1285.     void (*cb)();
  1286.     if ((cb = statePtr->outputCallback) != NULL) {
  1287.         if (netHppiDebug) {
  1288.         printf ("Received a HPPI testing interrupt.\n");
  1289.         }
  1290.         statePtr->outputCallback = NULL;
  1291.         MASTER_UNLOCK (&interPtr->mutex);
  1292.         (cb)(statePtr->outputClientData, SUCCESS);
  1293.         MASTER_LOCK (&interPtr->mutex);
  1294.     } else {
  1295.         printf ("Received a HPPI testing interrupt with no callback.\n");
  1296.     }
  1297.     goto intrExit;
  1298.     }
  1299. #ifndef CLEAN
  1300.     if (netHppiDebug) {
  1301.     printf("Received an HPPI interrupt.\n");
  1302.     }
  1303. #endif
  1304.     xrbPtr = statePtr->nextToHostPtr;
  1305. #ifndef CLEAN
  1306.     if (netHppiTrace) {
  1307.     NEXT_TRACE(statePtr, &tracePtr);
  1308.     tracePtr->event = INTERRUPT;
  1309.     Timer_GetCurrentTicks(&tracePtr->ticks);
  1310.     }
  1311.     if (netHppiDebug) {
  1312.     printf ("NetHppiIntr: xrbPtr = 0x%x\n", xrbPtr);
  1313.     }
  1314. #endif
  1315.     processed = 0;
  1316.     while(xrbPtr->filled != 0) {
  1317.     /*
  1318.      * Compute the next xrb to the host.
  1319.      */
  1320.     if (xrbPtr == statePtr->lastToHostPtr) {
  1321.         nextXRBPtr = statePtr->firstToHostPtr;
  1322.     } else {
  1323.         nextXRBPtr = xrbPtr + 1;
  1324.     }
  1325. #ifndef CLEAN
  1326.     if (netHppiDebug) {
  1327.         printf ("NetHppiIntr: xrbPtr = 0x%x\n", xrbPtr);
  1328.     }
  1329. #endif
  1330.     if (xrbPtr->filled == DEV_HPPI_FILLED_CMD) {
  1331.         Dev_HppiCmdHdr*    hdr;
  1332.         statePtr->nextToHostPtr = nextXRBPtr;
  1333. #ifndef CLEAN
  1334.         if (netHppiDebug) {
  1335.         hdr = (Dev_HppiCmdHdr*)&(xrbPtr->request);
  1336.         printf ("NetHppiIntr: processing command 0x%x\n", hdr->opcode);
  1337.         }
  1338. #endif
  1339.         /*
  1340.          * This could get complicated, and will always require callbacks
  1341.          * anyway, so just schedule callback to process the return.  The
  1342.          * command will always have an xrbId and xrbBufId which identify
  1343.          * the originator of the command.  Don't clear the filled field;
  1344.          * that will be done by the callback.
  1345.          */
  1346.         Proc_CallFunc (NetHppiCmdCallback, (ClientData)xrbPtr, 0);
  1347.         processed += 1;
  1348.     } else {
  1349.         hdrPtr = (NetUltraRequestHdr *) &xrbPtr->request;
  1350.         infoPtr = statePtr->tagToXRBInfo[(int)hdrPtr->infoPtr];
  1351.         statePtr->nextToHostPtr = nextXRBPtr;
  1352.         dmaPtr = &xrbPtr->dma;
  1353.         if (!(dmaPtr->cmd & NET_ULTRA_DMA_CMD_FROM_ADAPTER)) {
  1354.         printf("NetHppiIntr: cmd (0x%x) not from adapter?\n", dmaPtr->cmd);
  1355.         goto endLoop;
  1356.         }
  1357.         if ((dmaPtr->cmd & NET_ULTRA_DMA_CMD_MASK) != NET_ULTRA_DMA_CMD_XRB) {
  1358.         printf("NetHppiIntr: dmaPtr->cmd = 0x%x\n", dmaPtr->cmd);
  1359.         goto endLoop;
  1360.         }
  1361.         if (infoPtr->flags & NET_ULTRA_INFO_PENDING) {
  1362. #ifndef CLEAN
  1363.         if (netHppiDebug) {
  1364.             printf("NetHppiIntr: processing 0x%x\n", infoPtr);
  1365.         }
  1366.         if (netHppiTrace) {
  1367.             NEXT_TRACE(statePtr, &tracePtr);
  1368.             tracePtr->event = PROCESS_XRB;
  1369.             tracePtr->index = xrbPtr - statePtr->firstToHostPtr;
  1370.             tracePtr->infoPtr = infoPtr;
  1371.             Timer_GetCurrentTicks(&tracePtr->ticks);
  1372.         }
  1373. #endif
  1374.         infoPtr->xrbPtr = xrbPtr;
  1375.         /*
  1376.          * Mark the info as not pending.
  1377.          * Clearing the pending bit ensures
  1378.          * that this packet does not get processed twice, since the
  1379.          * master lock around the interface will get released before
  1380.          * calling the RPC system, so that the RPC system can
  1381.          * output a packet. Do not
  1382.          * clear the filled bit since we are using the contents of
  1383.          * the xrb and we don't want the adapter to overwrite it
  1384.          * yet. 
  1385.          */
  1386.         infoPtr->flags &= ~NET_ULTRA_INFO_PENDING;
  1387.         if (infoPtr->doneProc != NILPROC) {
  1388.             (infoPtr->doneProc)(interPtr, infoPtr);
  1389.         }
  1390.         if (infoPtr->flags & NET_ULTRA_INFO_STD_BUFFER) {
  1391.             if (infoPtr->flags & NET_ULTRA_INFO_REMAP) {
  1392.             VmMach_DMAFree(hdrPtr->size, 
  1393.                        VME_TO_DVMA(hdrPtr->buffer, statePtr));
  1394.             buffer = infoPtr->buffer;
  1395.             } else {
  1396.             buffer = VME_TO_BUFFER(hdrPtr->buffer, statePtr);
  1397.             }
  1398.             List_InitElement((List_Links *) buffer);
  1399.             List_Insert((List_Links *) buffer,
  1400.                 LIST_ATREAR(statePtr->freeBufferList));
  1401.         }
  1402.         List_Remove((List_Links *) infoPtr);
  1403.         List_Insert((List_Links *) infoPtr, 
  1404.                 LIST_ATREAR(statePtr->freeXRBInfoList));
  1405.         processed++;
  1406.         } else {
  1407. #ifndef CLEAN
  1408.         if (netHppiTrace) {
  1409.             NEXT_TRACE(statePtr, &tracePtr);
  1410.             tracePtr->event = INFO_NOT_PENDING;
  1411.             tracePtr->index = xrbPtr - statePtr->firstToHostPtr;
  1412.             tracePtr->infoPtr = infoPtr;
  1413.         }
  1414. #endif
  1415.         }
  1416.     }
  1417. endLoop: 
  1418.     xrbPtr->filled = 0;
  1419.     xrbPtr = nextXRBPtr;
  1420.     }
  1421.  
  1422.  
  1423.     /*
  1424.      * Check to see if the HPPI-D board has a message for us.
  1425.      */
  1426.     hppiStatus = statePtr->hppidReg->status;
  1427.     if ((hppiStatus & NET_HPPI_DST_STATUS_ALIVE_MASK) ==
  1428.     NET_HPPI_DST_STATUS_ERROR) {
  1429.     statePtr->flags |= NET_HPPI_STATE_DST_ERROR;
  1430.     Proc_CallFunc (NetHppiMsgCallback, (ClientData)interPtr, 0);
  1431.     } else if (!(hppiStatus & DEV_HPPI_OFIFO_EMPTY)) {
  1432.     Proc_CallFunc (NetHppiMsgCallback, (ClientData)interPtr, 0);
  1433.     }
  1434.     
  1435.     /*
  1436.      * Check to see if the HPPI-S board has an error message for us.
  1437.      */
  1438.     hppiStatus = statePtr->hppisReg->status;
  1439.     if ((hppiStatus & NET_HPPI_SRC_STATUS_ALIVE_MASK) ==
  1440.     NET_HPPI_SRC_STATUS_ERROR) {
  1441.     statePtr->flags |= NET_HPPI_STATE_SRC_ERROR;
  1442.     Proc_CallFunc (NetHppiMsgCallback, (ClientData)interPtr, 0);
  1443.     }
  1444.  
  1445. #ifndef CLEAN
  1446.     if (processed == 0) {
  1447.     if (netHppiDebug) {
  1448.         printf("NetHppiIntr: didn't process any packets.\n");
  1449.     }
  1450.     }
  1451. #endif
  1452.   intrExit:
  1453.     MASTER_UNLOCK(&interPtr->mutex);
  1454.  
  1455. }
  1456.  
  1457. /*
  1458.  *----------------------------------------------------------------------
  1459.  *
  1460.  * NetHppiSetupBoard
  1461.  *
  1462.  *    Send a setup command to the HPPI-D board.  This should only be done
  1463.  *    immediately after code is downloaded and run on the HPPI-D board.
  1464.  *
  1465.  * Results:
  1466.  *    SUCCESS if command went OK
  1467.  *    various failure codes otherwise
  1468.  *
  1469.  * Side effects:
  1470.  *    A setup command is sent to the adapter.
  1471.  *
  1472.  *----------------------------------------------------------------------
  1473.  */
  1474. static
  1475. ReturnStatus
  1476. NetHppiSetupBoard (statePtr)
  1477.     NetHppiState    *statePtr;
  1478. {
  1479.     Dev_HppiSetup    setupCmd;
  1480.     ReturnStatus    status = SUCCESS;
  1481.  
  1482.     /*
  1483.      * set up the configuration registers appropriately, in case
  1484.      * they were cleared when the link board was reset.
  1485.      *
  1486.      */
  1487.     statePtr->hppisReg->config = NET_HPPI_SRC_CONFIG_VALUE;
  1488.     statePtr->hppidReg->config = NET_HPPI_DST_CONFIG_VALUE;
  1489.  
  1490.     setupCmd.hdr.opcode = DEV_HPPI_SETUP;
  1491.     setupCmd.hdr.magic = DEV_HPPI_DEST_MAGIC;
  1492.     setupCmd.reqBlockSize = sizeof (NetUltraXRB);
  1493.     setupCmd.queueAddress = (uint32)(statePtr->firstToHostVME);
  1494.     setupCmd.queueSize = NET_HPPI_NUM_TO_HOST;
  1495.     status = NetHppiSendCmd (statePtr, sizeof (setupCmd),
  1496.                  (Address)&setupCmd, 0);
  1497.  
  1498.     return (status);
  1499. }
  1500.  
  1501. /*----------------------------------------------------------------------
  1502.  *
  1503.  * NetHppiRomCmd --
  1504.  *
  1505.  *    Send a command to the ROM monitor of one of the boards.  After
  1506.  *    the command is sent, the routine busy-waits for a reply.
  1507.  *
  1508.  * Results:
  1509.  *    SUCCESS if the command was sent OK.
  1510.  *    DEV_TIMEOUT if the device didn't complete the command
  1511.  *
  1512.  * Side effects:
  1513.  *    A command is sent to one of the HPPI boards.
  1514.  *
  1515.  *----------------------------------------------------------------------
  1516.  */
  1517. static
  1518. ReturnStatus
  1519. NetHppiRomCmd (interPtr, cmdBufPtr, cmdBufSize, responsePtr, responseSizePtr,
  1520.            flags)
  1521.     Net_Interface    *interPtr;
  1522.     int            *cmdBufPtr;
  1523.     int            cmdBufSize;
  1524.     int            *responsePtr;
  1525.     int            *responseSizePtr;
  1526.     int            flags;
  1527. {
  1528.     NetHppiState    *statePtr = (NetHppiState *)interPtr->interfaceData;
  1529.     ReturnStatus    status = SUCCESS;
  1530.     volatile uint32    *boardStatus;
  1531.     int            which;
  1532.     int            responseSize;
  1533.     int            garbage;
  1534.     int            excess = 0;
  1535.  
  1536.     if (netHppiDebug) {
  1537.     printf ("NetHppiRomCmd: starting cmd.\n");
  1538.     }
  1539.  
  1540.     if (flags & NET_HPPI_SRC_CMD) {
  1541.     if (!(statePtr->flags & NET_HPPI_STATE_SRC_EPROM)) {
  1542.         printf ("NetHppiRomCmd: SRC board not running EPROM code\n");
  1543.         return (FAILURE);
  1544.     }
  1545.     which = NET_HPPI_SRC_CMD;
  1546.     boardStatus = &(statePtr->hppisReg->status);
  1547.     } else {
  1548.     if (!(statePtr->flags & NET_HPPI_STATE_DST_EPROM)) {
  1549.         printf ("NetHppiRomCmd: DST board not running EPROM code\n");
  1550.         return (FAILURE);
  1551.     }
  1552.     which = 0;
  1553.     boardStatus = &(statePtr->hppidReg->status);
  1554.     }
  1555.  
  1556.     responseSize = 0;
  1557.     MASTER_LOCK (&interPtr->mutex);
  1558.  
  1559.     NetHppiCopyToFifo (cmdBufPtr, cmdBufSize, statePtr, which);
  1560.  
  1561.     WAIT_FOR_BIT_CLEAR (boardStatus, NET_HPPI_DELAY, DEV_HPPI_OFIFO_EMPTY);
  1562.  
  1563.     status = NetHppiCopyFromFifo (&responseSize, sizeof (responseSize),
  1564.                   statePtr, which);
  1565.     if (status != SUCCESS) {
  1566.     printf ("NetHppiRomCmd: command timed out.\n");
  1567.     status = DEV_TIMEOUT;
  1568.     goto exit;
  1569.     }
  1570.     *(responsePtr++) = responseSize;
  1571.     responseSize -= 4;
  1572.     if (responseSize > (*responseSizePtr)) {
  1573.     excess = responseSize - *responseSizePtr;
  1574.     responseSize = *responseSizePtr;
  1575.     }
  1576.  
  1577.     status = NetHppiCopyFromFifo (responsePtr, responseSize, statePtr, which);
  1578.     while (excess > 0) {
  1579.     (void)NetHppiCopyFromFifo (&garbage, sizeof(garbage), statePtr, which);
  1580.     excess -= sizeof (garbage);
  1581.     }
  1582.  
  1583.     /*
  1584.      * Correct so the size includes the first (size) word
  1585.      */
  1586.     *responseSizePtr = responseSize + 4;
  1587.  
  1588. exit:    
  1589.     MASTER_UNLOCK (&interPtr->mutex);
  1590.  
  1591.     if (netHppiDebug) {
  1592.     printf ("NetHppiRomCmd: returning...\n");
  1593.     }
  1594.     return (status);
  1595. }
  1596.  
  1597. /*
  1598.  *----------------------------------------------------------------------
  1599.  *
  1600.  * NetHppiIOControl --
  1601.  *
  1602.  *    Handle ioctls for the HPPI boards.
  1603.  *
  1604.  * Results:
  1605.  *    SUCCESS if the ioctl was performed successfully, a standard
  1606.  *    Sprite error code otherwise.
  1607.  *
  1608.  * Side effects:
  1609.  *    Commands may be sent to the adapter and/or the either HPPI board,
  1610.  *    and the adapter state and board states may change.
  1611.  *
  1612.  *----------------------------------------------------------------------
  1613.  */
  1614.  
  1615. /*ARGSUSED*/
  1616. ReturnStatus
  1617. NetHppiIOControl(interPtr, ioctlPtr, replyPtr)
  1618.     Net_Interface *interPtr;    /* Interface on which to perform ioctl. */
  1619.     Fs_IOCParam *ioctlPtr;    /* Standard I/O Control parameter block */
  1620.     Fs_IOReply *replyPtr;    /* Size of outBuffer and returned signal */
  1621. {
  1622.     ReturnStatus status = SUCCESS;
  1623.     int    fmtStatus;
  1624.     int inSize;
  1625.     int outSize;
  1626.     NetHppiState    *statePtr = (NetHppiState *) interPtr->interfaceData;
  1627.  
  1628.     if (netHppiDebug) {
  1629.     printf("NetHppiIOControl: command = 0x%x\n", ioctlPtr->command);
  1630.     }
  1631.     if ((ioctlPtr->command & ~0xffff) != IOC_HPPI) {
  1632.     return DEV_INVALID_ARG;
  1633.     }
  1634.     switch(ioctlPtr->command) {
  1635.     case IOC_HPPI_SET_FLAGS:
  1636.     case IOC_HPPI_RESET_FLAGS:
  1637.     case IOC_HPPI_GET_FLAGS:
  1638.         return GEN_NOT_IMPLEMENTED;
  1639.         break;
  1640.     case IOC_HPPI_DEBUG: {
  1641.         int    value;
  1642.         outSize = sizeof(int);
  1643.         inSize = ioctlPtr->inBufSize;
  1644.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
  1645.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1646.                 (Address) &value);
  1647.         if (fmtStatus != 0) {
  1648.         printf("Format of IOC_HPPI_DEBUG parameter failed, 0x%x\n",
  1649.             fmtStatus);
  1650.         return GEN_INVALID_ARG;
  1651.         }
  1652.         netHppiDebug = value;
  1653.         break;
  1654.     }
  1655.  
  1656.     case IOC_HPPI_TRACE: {
  1657.         int    value;
  1658.         outSize = sizeof(int);
  1659.         inSize = ioctlPtr->inBufSize;
  1660.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
  1661.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1662.                 (Address) &value);
  1663.         if (fmtStatus != 0) {
  1664.         printf("Format of IOC_HPPI_TRACE parameter failed, 0x%x\n",
  1665.             fmtStatus);
  1666.         return GEN_INVALID_ARG;
  1667.         }
  1668.         netHppiTrace = value;
  1669.         break;
  1670.     }
  1671.     case IOC_HPPI_RESET: 
  1672.         Net_HppiReset(interPtr);
  1673.         break;
  1674.     case IOC_HPPI_HARD_RESET:
  1675.         Net_HppiHardReset(interPtr);
  1676.         break;
  1677. #if 0
  1678.     case IOC_HPPI_SRC_RESET:
  1679.         break;
  1680.     case IOC_HPPI_DST_RESET:
  1681.         break;
  1682. #endif
  1683.     case IOC_HPPI_START: {
  1684.         MASTER_LOCK(&interPtr->mutex);
  1685.         status = NetHppiStart(statePtr);
  1686.         MASTER_UNLOCK(&interPtr->mutex);
  1687.         break;
  1688.     }
  1689.     case IOC_HPPI_GET_ADAP_INFO:
  1690.         return GEN_NOT_IMPLEMENTED;
  1691.         break;
  1692.     case IOC_HPPI_DIAG:
  1693.     case IOC_HPPI_EXTENDED_DIAG:
  1694.         return GEN_NOT_IMPLEMENTED;
  1695.         break;
  1696.  
  1697.     case IOC_HPPI_WRITE_REG: {
  1698.         Dev_HppiRegCmd writeCmd;
  1699.  
  1700.         inSize = ioctlPtr->inBufSize;
  1701.         outSize = sizeof (writeCmd);
  1702.         fmtStatus = Fmt_Convert ("www", ioctlPtr->format, &inSize,
  1703.                      ioctlPtr->inBuffer, mach_Format,
  1704.                      &outSize, (Address)&writeCmd);
  1705.         if (fmtStatus != FMT_OK) {
  1706.         printf ("Format of HPPI_WRITE_REG parameter failed, 0x%x\n",
  1707.             fmtStatus);
  1708.         return GEN_INVALID_ARG;
  1709.         }
  1710.         if (writeCmd.board == DEV_HPPI_SRC_BOARD) {
  1711.         if (writeCmd.offset >= sizeof (NetHppiSrcReg)) {
  1712.             printf ("HPPI_WRITE_REG: bad SRC register offset 0x%x\n",
  1713.                 writeCmd.offset);
  1714.             return GEN_INVALID_ARG;
  1715.         }
  1716.         status = Mach_Probe (sizeof (int), (char *)&(writeCmd.value),
  1717.             (char *)(statePtr->hppisReg) + writeCmd.offset);
  1718.         } else if (writeCmd.board == DEV_HPPI_DST_BOARD) {
  1719.         if (writeCmd.offset >= sizeof (NetHppiDestReg)) {
  1720.             printf ("HPPI_WRITE_REG: bad DST register offset 0x%x\n",
  1721.                 writeCmd.offset);
  1722.             return GEN_INVALID_ARG;
  1723.         }
  1724.         status = Mach_Probe (sizeof (int), (char *)&(writeCmd.value),
  1725.             (char *)(statePtr->hppidReg) + writeCmd.offset);
  1726.         } else if (writeCmd.board == DEV_HPPI_IOP_BOARD) {
  1727.         if (writeCmd.offset >= sizeof (NetHppiIopReg)) {
  1728.             printf ("HPPI_WRITE_REG: bad IOP register offset 0x%x\n",
  1729.                 writeCmd.offset);
  1730.             return GEN_INVALID_ARG;
  1731.         }
  1732.         status = Mach_Probe (sizeof (int), (char *)&(writeCmd.value),
  1733.             (char *)(statePtr->iopReg) + writeCmd.offset);
  1734.         } else {
  1735.         return GEN_INVALID_ARG;
  1736.         }
  1737.         break;
  1738.     }
  1739.  
  1740.     case IOC_HPPI_READ_REG: {
  1741.         Dev_HppiRegCmd readCmd;
  1742.         uint32 regValue;
  1743.  
  1744.         inSize = ioctlPtr->inBufSize;
  1745.         outSize = sizeof (readCmd);
  1746.         fmtStatus = Fmt_Convert ("www", ioctlPtr->format, &inSize,
  1747.                      ioctlPtr->inBuffer, mach_Format,
  1748.                      &outSize, (Address)&readCmd);
  1749.         if (fmtStatus != FMT_OK) {
  1750.         printf ("Format of HPPI_READ_REG parameter failed, 0x%x\n",
  1751.             fmtStatus);
  1752.         return GEN_INVALID_ARG;
  1753.         }
  1754.         if (readCmd.board == DEV_HPPI_SRC_BOARD) {
  1755.         if (readCmd.offset >= sizeof (NetHppiSrcReg)) {
  1756.             printf ("HPPI_READ_REG: bad SRC register offset 0x%x\n",
  1757.                 readCmd.offset);
  1758.             return GEN_INVALID_ARG;
  1759.         }
  1760.         status = Mach_Probe (sizeof(int),(char *)(statePtr->hppisReg) +
  1761.                      readCmd.offset, (char *)®Value);
  1762.         } else if (readCmd.board == DEV_HPPI_DST_BOARD) {
  1763.         if (readCmd.offset >= sizeof (NetHppiDestReg)) {
  1764.             printf ("HPPI_READ_REG: bad DST register offset 0x%x\n",
  1765.                 readCmd.offset);
  1766.             return GEN_INVALID_ARG;
  1767.         }
  1768.         status = Mach_Probe (sizeof(int),(char *)(statePtr->hppidReg) +
  1769.                      readCmd.offset, (char *)®Value);
  1770.         } else if (readCmd.board == DEV_HPPI_IOP_BOARD) {
  1771.         if (readCmd.offset >= sizeof (NetHppiIopReg)) {
  1772.             printf ("HPPI_READ_REG: bad IOP register offset 0x%x\n",
  1773.                 readCmd.offset);
  1774.             return GEN_INVALID_ARG;
  1775.         }
  1776.         status = Mach_Probe (sizeof(int), (char *)(statePtr->iopReg) +
  1777.                      readCmd.offset, (char *)®Value);
  1778.         } else {
  1779.         return GEN_INVALID_ARG;
  1780.         }
  1781.         readCmd.value = regValue;
  1782.  
  1783.         if (ioctlPtr->outBufSize < sizeof (readCmd)) {
  1784.         printf ("HPPI_READ_REG: return buffer too small\n");
  1785.         return GEN_INVALID_ARG;
  1786.         }
  1787.         inSize = outSize = sizeof (readCmd);
  1788.         fmtStatus = Fmt_Convert ("www", mach_Format, &inSize,
  1789.                      (Address)&readCmd, ioctlPtr->format,
  1790.                      &outSize, (Address)ioctlPtr->outBuffer);
  1791.         if (fmtStatus != FMT_OK) {
  1792.         printf ("Format of HPPI_READ_REG output failed, 0x%x\n",
  1793.             fmtStatus);
  1794.         return GEN_INVALID_ARG;
  1795.         }
  1796.         break;
  1797.     }
  1798.  
  1799.     case IOC_HPPI_GO: {
  1800.         Dev_HppiGo goCmd;
  1801.         int flags;
  1802.         Dev_HppiRomGo hppiCmd;
  1803.         Dev_HppiRomGoReply hppiReply;
  1804.         int replySize;
  1805.  
  1806.         inSize = ioctlPtr->inBufSize;
  1807.         outSize = sizeof (goCmd);
  1808.         fmtStatus = Fmt_Convert ("w2", ioctlPtr->format, &inSize,
  1809.                      ioctlPtr->inBuffer, mach_Format,
  1810.                      &outSize, (Address)&goCmd);
  1811.         if (fmtStatus != FMT_OK) {
  1812.         printf ("Format of HPPI GO parameter failed, 0x%x\n",
  1813.             fmtStatus);
  1814.         return GEN_INVALID_ARG;
  1815.         }
  1816.         /*
  1817.          * Format the GO command
  1818.          */
  1819.         hppiCmd.hdr.length = sizeof (hppiCmd);
  1820.         hppiCmd.hdr.commandId = DEV_HPPI_START_CODES;
  1821.         hppiCmd.hdr.callerPid = 0;
  1822.         hppiCmd.startAddress = goCmd.startAddress;
  1823.  
  1824.         if ((goCmd.board != DEV_HPPI_SRC_BOARD) &&
  1825.         (goCmd.board != DEV_HPPI_DST_BOARD)) {
  1826.         printf ("IOC_HPPI_GO: bad board id (0x%x)\n", goCmd.board);
  1827.         return GEN_INVALID_ARG;
  1828.         }
  1829.         flags = (goCmd.board == DEV_HPPI_SRC_BOARD) ? NET_HPPI_SRC_CMD : 0;
  1830.         replySize = sizeof (hppiReply);
  1831.         status = NetHppiRomCmd (interPtr, &hppiCmd, sizeof (hppiCmd),
  1832.                     &hppiReply, &replySize, flags);
  1833.  
  1834.         if (status != SUCCESS) {
  1835.         printf ("IOC_HPPI_GO: couldn't start code (0x%x)\n", status);
  1836.         return FAILURE;
  1837.         }
  1838.         if ((hppiReply.hdr.responseId != DEV_HPPI_START_CODES) ||
  1839.         (hppiReply.hdr.status != 0) ||
  1840.         (hppiReply.startAddress != goCmd.startAddress)) {
  1841.         printf ("IOC_HPPI_GO: response was wrong (r%d s%d a0x%x)\n",
  1842.             hppiReply.hdr.responseId, hppiReply.hdr.status,
  1843.             hppiReply.startAddress);
  1844.         return FAILURE;
  1845.         }
  1846.         if (goCmd.board == DEV_HPPI_SRC_BOARD) {
  1847.         statePtr->flags &= ~NET_HPPI_STATE_SRC_EPROM;
  1848.         } else {
  1849.         statePtr->flags &= ~NET_HPPI_STATE_DST_EPROM;
  1850.         }
  1851.  
  1852.         if (!(statePtr->flags & (NET_HPPI_STATE_SRC_EPROM |
  1853.                      NET_HPPI_STATE_DST_EPROM))) {
  1854.         statePtr->flags |= NET_HPPI_STATE_NORMAL;
  1855.         }
  1856.         break;
  1857.     }
  1858.  
  1859.     case IOC_HPPI_LOAD: {
  1860.         Dev_HppiLoadHdr loadCmdHdr;
  1861.         Dev_HppiRomWrite *loadPtr;
  1862.         Dev_HppiRomWriteReply reply;
  1863.         int replySize = sizeof (reply);
  1864.         int flags;
  1865.  
  1866.         inSize = ioctlPtr->inBufSize;
  1867.         outSize = sizeof (loadCmdHdr); 
  1868.         fmtStatus = Fmt_Convert ("w3", ioctlPtr->format, &inSize,
  1869.                      ioctlPtr->inBuffer, mach_Format,
  1870.                      &outSize, (Address)&loadCmdHdr);
  1871.         if (fmtStatus != FMT_OK) {
  1872.         printf ("Format of IOC_HPPI_LOAD parameter failed, 0x%x\n",
  1873.             fmtStatus);
  1874.         return GEN_INVALID_ARG;
  1875.         }
  1876.         inSize  = outSize = loadCmdHdr.size;
  1877.         if (inSize >= DEV_HPPI_MAX_ROM_CMD_SIZE) {
  1878.         printf ("IOC_HPPI_LOAD: load data too big (0x%x)\n", inSize);
  1879.         return GEN_INVALID_ARG;
  1880.         }
  1881.         loadPtr = (Dev_HppiRomWrite *)
  1882.         malloc (sizeof (Dev_HppiRomWrite) + loadCmdHdr.size);
  1883.         if (loadPtr == NULL) {
  1884.         printf ("IOC_HPPI_LOAD: unable to allocate space\n");
  1885.         return FAILURE;
  1886.         }
  1887.         fmtStatus = Fmt_Convert ("w*", ioctlPtr->format, &inSize,
  1888.         (char *)ioctlPtr->inBuffer + sizeof (loadCmdHdr),
  1889.         mach_Format, &outSize, (Address)(loadPtr->data));
  1890.         if (fmtStatus != FMT_OK) {
  1891.         printf ("Format of IOC_HPPI_LOAD data failed, 0x%x\n",
  1892.             fmtStatus);
  1893.         status = GEN_INVALID_ARG;
  1894.         goto exitLoad;
  1895.         }
  1896.         loadPtr->hdr.commandId = DEV_HPPI_PUT_MEMORY;
  1897.         loadPtr->hdr.length = (sizeof (Dev_HppiRomWrite) - sizeof (int)) +
  1898.         loadCmdHdr.size;
  1899.         loadPtr->hdr.callerPid = 0;
  1900.         loadPtr->writeAddress = loadCmdHdr.startAddress;
  1901.         loadPtr->writeWords = loadCmdHdr.size / sizeof(int);
  1902.         flags =
  1903.         (loadCmdHdr.board == DEV_HPPI_SRC_BOARD) ? NET_HPPI_SRC_CMD :0;
  1904.         status = NetHppiRomCmd (interPtr, loadPtr, loadPtr->hdr.length,
  1905.                     &reply, &replySize, flags);
  1906.         if ((status == SUCCESS) && (
  1907.         (reply.hdr.responseId != DEV_HPPI_PUT_MEMORY) ||
  1908.         (reply.hdr.status != 0) ||
  1909.         (reply.wordsWritten != loadPtr->writeWords))) {
  1910.         printf ("IOC_HPPI_LOAD: load failed (0x%x words)\n",
  1911.             reply.wordsWritten);
  1912.         status = FAILURE;
  1913.         }
  1914.       exitLoad:
  1915.         free ((Address)loadPtr);
  1916.         break;
  1917.     }
  1918.  
  1919.     case IOC_HPPI_SRC_ROM_CMD:
  1920.     case IOC_HPPI_DST_ROM_CMD: {
  1921.         int *cmdBufPtr;
  1922.         static int replyBuf[NET_HPPI_ROM_MAX_REPLY];
  1923.         int replySize;
  1924.         int flags;
  1925.  
  1926.         inSize = ioctlPtr->inBufSize;
  1927.         cmdBufPtr = (int *)malloc (inSize);
  1928.         outSize = inSize;
  1929.         fmtStatus = Fmt_Convert ("w*", ioctlPtr->format, &inSize,
  1930.                      ioctlPtr->inBuffer, mach_Format,
  1931.                      &outSize, (Address)cmdBufPtr);
  1932.         if (fmtStatus != FMT_OK) {
  1933.         printf ("Format of HPPI ROM parameter failed, 0x%x\n",
  1934.             fmtStatus);
  1935.         status = GEN_INVALID_ARG;
  1936.         goto exitRomCmd;
  1937.         }
  1938.         flags = (ioctlPtr->command == IOC_HPPI_SRC_ROM_CMD) ?
  1939.         NET_HPPI_SRC_CMD : 0;
  1940.         status = NetHppiRomCmd (interPtr, cmdBufPtr, inSize, replyBuf,
  1941.                     &replySize, flags);
  1942.         if (status == SUCCESS) {
  1943.         if (replySize > ioctlPtr->outBufSize) {
  1944.             printf ("IOC_HPPI_ROM_CMD: reply too long\n");
  1945.             goto exitRomCmd;
  1946.         }
  1947.         inSize = replySize;
  1948.         fmtStatus = Fmt_Convert("w*", mach_Format, &replySize,
  1949.                     (Address) replyBuf,
  1950.                     ioctlPtr->format, &outSize,
  1951.                     ioctlPtr->outBuffer);
  1952.         if (fmtStatus != 0) {
  1953.             printf("Format of HPPI ROM response failed, 0x%x\n",
  1954.                fmtStatus);
  1955.             status = GEN_INVALID_ARG;
  1956.         }
  1957.         } else {
  1958.         printf ("IOC_HPPI_ROM_CMD: command failed 0x%x\n", status);
  1959.         }
  1960.       exitRomCmd:
  1961.         free ((Address)cmdBufPtr);
  1962.         break;
  1963.     }
  1964.     case IOC_HPPI_SETUP: {
  1965.         MASTER_LOCK (&interPtr->mutex);
  1966.         status = NetHppiSetupBoard (statePtr);
  1967.         MASTER_UNLOCK (&interPtr->mutex);
  1968.         break;
  1969.     }
  1970.  
  1971.     case IOC_HPPI_SEND_DGRAM: {
  1972.         Dev_UltraSendDgram        dgram;
  1973.         int *tmpBuf = (int *)NIL;
  1974.         inSize = ioctlPtr->inBufSize;
  1975.         outSize = sizeof(dgram);
  1976.         fmtStatus = Fmt_Convert("{{b8}w{w2}w2b*}",
  1977.                     ioctlPtr->format, &inSize,
  1978.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1979.                 (Address) &dgram);
  1980.         if (fmtStatus != 0) {
  1981.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  1982.             return GEN_INVALID_ARG;
  1983.         } else {
  1984.             printf("NetHppiIOControl: Fmt_Convert returned %d\n",
  1985.             fmtStatus);
  1986.             return FAILURE;
  1987.         }
  1988.         }
  1989.         if (dgram.useBuffer != TRUE) {
  1990.         int i;
  1991.         tmpBuf = (int *)malloc (dgram.size);
  1992.         for (i = 0; i < dgram.size/4; i++) {
  1993.             *(tmpBuf + i) = i;
  1994.         }
  1995.         } 
  1996.         status = NetHppiSendDgram(interPtr, &dgram.address, dgram.count,
  1997.             dgram.size, 
  1998.             (dgram.useBuffer == TRUE) ? (Address) dgram.buffer :
  1999.             (Address) tmpBuf, &dgram.time);
  2000.         free ((char *)tmpBuf);
  2001.         inSize = sizeof(dgram);
  2002.         outSize = ioctlPtr->outBufSize;
  2003.         fmtStatus = Fmt_Convert("{{b8}w{w2}w2b*}", mach_Format, &inSize,
  2004.         (Address) &dgram, ioctlPtr->format, &outSize,
  2005.         (Address) ioctlPtr->outBuffer);
  2006.         if (fmtStatus != 0) {
  2007.         if (fmtStatus == FMT_OUTPUT_TOO_SMALL) {
  2008.             return GEN_INVALID_ARG;
  2009.         } else {
  2010.             printf(
  2011.             "NetHppiIOControl: Fmt_Convert returned %d\n",
  2012.             fmtStatus);
  2013.             return FAILURE;
  2014.         }
  2015.         }
  2016.         break;
  2017.     }
  2018.  
  2019.     case IOC_HPPI_RECV_DGRAM: {
  2020.         if (statePtr->flags & NET_HPPI_STATE_SINK) {
  2021.         if (netHppiDebug) {
  2022.             printf ("NetHppiIOControl: already sinking dgrams.\n");
  2023.         }
  2024.         return FAILURE;
  2025.         }
  2026.         statePtr->flags |= NET_HPPI_STATE_SINK;
  2027.         statePtr->flags &= ~NET_HPPI_STATE_NORMAL;
  2028.         Proc_CallFunc (NetHppiRecvDgram, (ClientData)interPtr, 0);
  2029.         break;
  2030.     }
  2031.  
  2032.     case IOC_HPPI_ECHO: {
  2033.         Dev_UltraEcho        echo;
  2034.         inSize = ioctlPtr->inBufSize;
  2035.         outSize = sizeof(echo);
  2036.         fmtStatus = Fmt_Convert("{w}", ioctlPtr->format, &inSize,
  2037.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  2038.                 (Address) &echo);
  2039.         if (fmtStatus != 0) {
  2040.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  2041.             return GEN_INVALID_ARG;
  2042.         } else {
  2043.             printf("NetHppiIOControl: Fmt_Convert returned %d\n",
  2044.             fmtStatus);
  2045.             return FAILURE;
  2046.         }
  2047.         }
  2048.         if (echo.echo == TRUE) {
  2049.         statePtr->flags |= NET_HPPI_STATE_ECHO;
  2050.         statePtr->flags &= ~NET_HPPI_STATE_NORMAL;
  2051.         } else {
  2052.         statePtr->flags &= ~NET_HPPI_STATE_ECHO;
  2053.         statePtr->flags |= NET_HPPI_STATE_NORMAL;
  2054.         }
  2055.         break;
  2056.     }
  2057.  
  2058.     case IOC_HPPI_SOURCE: {
  2059.         Dev_UltraSendDgram        dgram;
  2060.         inSize = ioctlPtr->inBufSize;
  2061.         outSize = sizeof(dgram);
  2062.         fmtStatus = Fmt_Convert("{{b8}w{w2}w2b*}",
  2063.                     ioctlPtr->format, &inSize,
  2064.                     ioctlPtr->inBuffer, mach_Format, &outSize,
  2065.                 (Address) &dgram);
  2066.         if (fmtStatus != 0) {
  2067.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  2068.             return GEN_INVALID_ARG;
  2069.         } else {
  2070.             printf("NetHppiIOControl: Fmt_Convert returned %d\n",
  2071.             fmtStatus);
  2072.             return FAILURE;
  2073.         }
  2074.         }
  2075.         status = NetHppiSource(interPtr, &dgram.address, dgram.count,
  2076.             dgram.size, 
  2077.             (dgram.useBuffer == TRUE) ? (Address) dgram.buffer :
  2078.             (Address) NIL, &dgram.time);
  2079.         inSize = sizeof(dgram);
  2080.         outSize = ioctlPtr->outBufSize;
  2081.         fmtStatus = Fmt_Convert("{{b8}w{w2}w2b*}", mach_Format, &inSize,
  2082.         (Address) &dgram, ioctlPtr->format, &outSize,
  2083.         (Address) ioctlPtr->outBuffer);
  2084.         if (fmtStatus != 0) {
  2085.         if (fmtStatus == FMT_OUTPUT_TOO_SMALL) {
  2086.             return GEN_INVALID_ARG;
  2087.         } else {
  2088.             printf(
  2089.             "NetHppiIOControl: Fmt_Convert returned %d\n",
  2090.             fmtStatus);
  2091.             return FAILURE;
  2092.         }
  2093.         }
  2094.         break;
  2095.     }
  2096.  
  2097.     case IOC_HPPI_SINK: {
  2098.         Dev_UltraSink        sink;
  2099.         int                value;
  2100.         outSize = sizeof(int);
  2101.         inSize = ioctlPtr->inBufSize;
  2102.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
  2103.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  2104.                 (Address) &value);
  2105.         if (fmtStatus != 0) {
  2106.         printf("Format of IOC_HPPI_SINK parameter failed, 0x%x\n",
  2107.             fmtStatus);
  2108.         return GEN_INVALID_ARG;
  2109.         }
  2110.         outSize = ioctlPtr->outBufSize;
  2111.         sink.packets = packetsSunk;
  2112.         Timer_SubtractTicks(sinkEndTime, sinkStartTime, &sink.time);
  2113.         Timer_TicksToTime(sink.time, &sink.time);
  2114.         inSize = sizeof(sink);
  2115.         fmtStatus = Fmt_Convert("w{w2}", mach_Format, &inSize,
  2116.                 (Address) &sink, ioctlPtr->format, &outSize,
  2117.                 ioctlPtr->outBuffer);
  2118.         if (fmtStatus != 0) {
  2119.         printf("Format of IOC_HPPI_SINK parameter failed, 0x%x\n",
  2120.             fmtStatus);
  2121.         return GEN_INVALID_ARG;
  2122.         }
  2123.         if (value > 0) {
  2124.         statePtr->flags |= NET_HPPI_STATE_SINK;
  2125.         statePtr->flags &= ~NET_HPPI_STATE_NORMAL;
  2126.         packetsSunk = 0;
  2127.         } else {
  2128.         statePtr->flags &= ~NET_HPPI_STATE_SINK;
  2129.         statePtr->flags |= NET_HPPI_STATE_NORMAL;
  2130.         }
  2131.         break;
  2132.     }
  2133.  
  2134.     case IOC_HPPI_ADDRESS: {
  2135.         /* 
  2136.          * Set the adapter address.  This is not the normal way to
  2137.          * do this (usually happens during route installation) but
  2138.          * it is useful for debugging. 
  2139.          */
  2140.         Net_UltraAddress    address;
  2141.         int            group;
  2142.         int            unit;
  2143.         inSize = ioctlPtr->inBufSize;
  2144.         outSize = sizeof(Net_UltraAddress);
  2145.         fmtStatus = Fmt_Convert("{b8}", ioctlPtr->format, &inSize,
  2146.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  2147.                 (Address) &address);
  2148.         if (fmtStatus != 0) {
  2149.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  2150.             return GEN_INVALID_ARG;
  2151.         } else {
  2152.             printf("NetUltraIOControl: Fmt_Convert returned %d\n",
  2153.             fmtStatus);
  2154.             return FAILURE;
  2155.         }
  2156.         }
  2157.         Net_UltraAddressGet(&address, &group, &unit);
  2158.         printf("Setting ultra address to %d/%d\n", group, unit); 
  2159.         MASTER_LOCK(&interPtr->mutex);
  2160.         status = Net_SetAddress(NET_ADDRESS_ULTRA,
  2161.             (Address) &address, 
  2162.             &interPtr->netAddress[NET_PROTO_RAW]);
  2163.         if (status != SUCCESS) {
  2164.         panic("NetHppiIOControl: Net_SetAddress failed\n");
  2165.         }
  2166.         MASTER_UNLOCK(&interPtr->mutex);
  2167.         break;
  2168.     }
  2169.  
  2170.     case IOC_HPPI_COLLECT_STATS: {
  2171.         int        value;
  2172.         inSize = ioctlPtr->inBufSize;
  2173.         outSize = sizeof(int);
  2174.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
  2175.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  2176.                 (Address) &value);
  2177.         if (fmtStatus != 0) {
  2178.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  2179.             return GEN_INVALID_ARG;
  2180.         } else {
  2181.             printf("NetHppiIOControl: Fmt_Convert returned %d\n",
  2182.             fmtStatus);
  2183.             return FAILURE;
  2184.         }
  2185.         }
  2186.         if (value == TRUE) {
  2187.         statePtr->flags |= NET_HPPI_STATE_STATS;
  2188.         } else {
  2189.         statePtr->flags &= ~NET_HPPI_STATE_STATS;
  2190.         }
  2191.         break;
  2192.     }
  2193.     case IOC_HPPI_CLEAR_STATS: {
  2194.         bzero((char *) &statePtr->stats, sizeof(statePtr->stats));
  2195.         break;
  2196.     }
  2197.     case IOC_HPPI_GET_STATS: {
  2198.         outSize = ioctlPtr->outBufSize;
  2199.         inSize = sizeof(Dev_UltraStats);
  2200.         fmtStatus = Fmt_Convert("w*", mach_Format, &inSize,
  2201.                 (Address) &statePtr->stats, 
  2202.                 ioctlPtr->format, &outSize,
  2203.                 ioctlPtr->outBuffer);
  2204.         if (fmtStatus != 0) {
  2205.         printf("Format of IOC_HPPI_GET_STATS parameter failed, 0x%x\n",
  2206.             fmtStatus);
  2207.         return GEN_INVALID_ARG;
  2208.         }
  2209.         break;
  2210.     }
  2211.  
  2212.     case IOC_HPPI_SET_TSAP: {
  2213.         char newTsap[4];
  2214.  
  2215.         inSize = outSize = sizeof (int);
  2216.         fmtStatus = Fmt_Convert("bbbb", ioctlPtr->format, &inSize,
  2217.                     ioctlPtr->inBuffer, mach_Format, &outSize,
  2218.                     (Address)&newTsap);
  2219.         if (fmtStatus != FMT_OK) {
  2220.         printf("Format of HPPI_SET_TSAP parm failed, 0x%x\n",
  2221.             fmtStatus);
  2222.         return GEN_INVALID_ARG;
  2223.         }
  2224.         if (netHppiDebug) {
  2225.         printf ("NetHppiIOControl: setting TSAP to %02x%02x%02x%02x\n",
  2226.             (unsigned char)newTsap[0], (unsigned char)newTsap[1],
  2227.             (unsigned char)newTsap[2], (unsigned char)newTsap[3]);
  2228.         }
  2229.         bcopy (newTsap, statePtr->curTsap, sizeof (statePtr->curTsap));
  2230.         break;
  2231.     }
  2232.     case IOC_HPPI_SET_BOARD_FLAGS:
  2233.     case IOC_HPPI_SET_SRC_BOARD_FLAGS:
  2234.     case IOC_HPPI_SET_DST_BOARD_FLAGS: {
  2235.         Dev_HppiSetBoardFlags flagCmd;
  2236.         inSize = outSize = sizeof (int);
  2237.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
  2238.                     ioctlPtr->inBuffer, mach_Format, &outSize,
  2239.                     (Address)&(flagCmd.flags));
  2240.         if (fmtStatus != FMT_OK) {
  2241.         printf("Format of HPPI_SET_BOARD_FLAGS parm failed, 0x%x\n",
  2242.             fmtStatus);
  2243.         return GEN_INVALID_ARG;
  2244.         }
  2245.         statePtr->boardFlags = flagCmd.flags;
  2246.         flagCmd.hdr.opcode = DEV_HPPI_SET_BOARD_FLAGS;
  2247.         if ((ioctlPtr->command == IOC_HPPI_SET_BOARD_FLAGS) ||
  2248.         (ioctlPtr->command == IOC_HPPI_SET_SRC_BOARD_FLAGS)) {
  2249.         status = NetHppiSendCmd (statePtr, sizeof (flagCmd),
  2250.                      (Address)&flagCmd, NET_HPPI_SRC_CMD);
  2251.         if (status != SUCCESS) {
  2252.             printf ("HPPI_SET_BOARD_FLAGS: SRC cmd failed\n");
  2253.             return (status);
  2254.         }
  2255.         }
  2256.         if ((ioctlPtr->command == IOC_HPPI_SET_BOARD_FLAGS) ||
  2257.         (ioctlPtr->command == IOC_HPPI_SET_DST_BOARD_FLAGS)) {
  2258.         status = NetHppiSendCmd (statePtr, sizeof (flagCmd),
  2259.                      (Address)&flagCmd, 0);
  2260.         if (status != SUCCESS) {
  2261.             printf ("HPPI_SET_BOARD_FLAGS: DST cmd failed\n");
  2262.             return (status);
  2263.         }
  2264.         }
  2265.         break;
  2266.     }
  2267.  
  2268.     /*
  2269.      * NOTE: there is a memory leak in the following IOC call.  This
  2270.      * call is to be used for testing purposes ONLY!
  2271.      */
  2272.     case IOC_HPPI_CONNECTION_OPEN: {
  2273.         Net_HppiConnection*    connPtr;
  2274.         Sync_Condition    gotOpen;
  2275.  
  2276.         connPtr = (Net_HppiConnection*)malloc(sizeof (Net_HppiConnection));
  2277.         inSize = outSize = sizeof (Net_HppiConnection);
  2278.         fmtStatus = Fmt_Convert("w9", ioctlPtr->format, &inSize,
  2279.                     ioctlPtr->inBuffer, mach_Format,
  2280.                     &outSize, (Address)connPtr);
  2281.         if (fmtStatus != FMT_OK) {
  2282.         printf("Format HPPI_CONNECTION_OPEN failed, 0x%x\n",
  2283.             fmtStatus);
  2284.         return GEN_INVALID_ARG;
  2285.         }
  2286.         connPtr->userData = (ClientData)&gotOpen;
  2287.         connPtr->interPtr = interPtr;
  2288.         connPtr->callbackProc = iocConnCallback;
  2289.         status = Net_HppiConnectionOpen (connPtr);
  2290.         if (status != SUCCESS) {
  2291.         printf ("HPPI_CONNECTION_OPEN: couldn't open 0x%x\n",
  2292.             status);
  2293.         return (FAILURE);
  2294.         }
  2295.         if (netHppiDebug) {
  2296.         printf ("HPPI_CONNECTION_OPEN: waiting...\n");
  2297.         }
  2298.         MASTER_LOCK (&(interPtr->mutex));
  2299.         Sync_MasterWait(&gotOpen, &(interPtr->mutex), FALSE);
  2300.         MASTER_UNLOCK (&(interPtr->mutex));
  2301.         if (netHppiDebug) {
  2302.         printf ("HPPI_CONNECTION_OPEN: returned from wait.\n");
  2303.         }
  2304.         connPtr->userData = (ClientData)connPtr;
  2305.         inSize = outSize = sizeof (Net_HppiConnection);
  2306.         fmtStatus = Fmt_Convert("w9", mach_Format, &inSize,
  2307.                     (Address)connPtr, ioctlPtr->format,
  2308.                     &outSize, ioctlPtr->outBuffer);
  2309.         if (fmtStatus != FMT_OK) {
  2310.         printf("Return format HPPI_CONNECTION_OPEN failed, 0x%x\n",
  2311.             fmtStatus);
  2312.         return GEN_INVALID_ARG;
  2313.         }
  2314.         status = connPtr->status;
  2315.         break;
  2316.     }
  2317.  
  2318.     case IOC_HPPI_CONNECTION_LISTEN: {
  2319.         Net_HppiConnection    conn, *connPtr;
  2320.         Sync_Condition    gotListen;
  2321.  
  2322.         inSize = outSize = sizeof (Net_HppiConnection);
  2323.         fmtStatus = Fmt_Convert("w9", ioctlPtr->format, &inSize,
  2324.                     ioctlPtr->inBuffer, mach_Format,
  2325.                     &outSize, (Address)&conn);
  2326.         if (fmtStatus != FMT_OK) {
  2327.         printf("Return format HPPI_CONNECTION_LISTEN failed, 0x%x\n",
  2328.             fmtStatus);
  2329.         return GEN_INVALID_ARG;
  2330.         }
  2331.         connPtr = (Net_HppiConnection*)conn.userData;
  2332.         connPtr->callbackProc = iocConnCallback;
  2333.         connPtr->interPtr = interPtr;
  2334.         connPtr->userData = (ClientData)&gotListen;
  2335.         status = Net_HppiConnectionListen (connPtr);
  2336.         if (status != SUCCESS) {
  2337.         printf ("HPPI_CONNECTION_LISTEN: couldn't listen 0x%x\n",
  2338.             status);
  2339.         return (FAILURE);
  2340.         }
  2341.         if (netHppiDebug) {
  2342.         printf ("HPPI_CONNECTION_LISTEN: waiting...\n");
  2343.         }
  2344.         MASTER_LOCK (&(interPtr->mutex));
  2345.         Sync_MasterWait(&gotListen, &(interPtr->mutex), FALSE);
  2346.         MASTER_UNLOCK (&(interPtr->mutex));
  2347.         if (netHppiDebug) {
  2348.         printf ("HPPI_CONNECTION_LISTEN: returned from wait.\n");
  2349.         }
  2350.         conn.status = connPtr->status;
  2351.         inSize = outSize = sizeof (Net_HppiConnection);
  2352.         fmtStatus = Fmt_Convert("w9", mach_Format, &inSize,
  2353.                     (Address)&conn, ioctlPtr->format,
  2354.                     &outSize, ioctlPtr->outBuffer);
  2355.         if (fmtStatus != FMT_OK) {
  2356.         printf("Return format HPPI_CONNECTION_LISTEN failed, 0x%x\n",
  2357.             fmtStatus);
  2358.         return GEN_INVALID_ARG;
  2359.         }
  2360.         break;
  2361.     }
  2362.  
  2363.     case IOC_HPPI_CONNECTION_SEND:
  2364.     case IOC_HPPI_CONNECTION_RECV:
  2365.     {
  2366.         Net_HppiConnection    conn, *connPtr;
  2367.         Net_HppiDataRequest    dataReq;
  2368.         Sync_Condition    dataDone;
  2369.  
  2370.         inSize = outSize = sizeof (Net_HppiConnection);
  2371.         fmtStatus = Fmt_Convert("w9", ioctlPtr->format, &inSize,
  2372.                     ioctlPtr->inBuffer, mach_Format,
  2373.                     &outSize, (Address)&conn);
  2374.         if (fmtStatus != FMT_OK) {
  2375.         printf("Return format HPPI_CONNECTION_xfer failed, 0x%x\n",
  2376.             fmtStatus);
  2377.         return GEN_INVALID_ARG;
  2378.         }
  2379.         connPtr = (Net_HppiConnection*)conn.userData;
  2380.         connPtr->interPtr = interPtr;
  2381.         dataReq.interPtr = interPtr;
  2382.         dataReq.connectionId = connPtr->connectionId;
  2383.         dataReq.userData = (ClientData)&dataDone;
  2384.         dataReq.callbackProc = iocXferCallback;
  2385.         dataReq.xferSize = 100;
  2386.         dataReq.xferOffset = 0;
  2387.         dataReq.sgSize = 1;
  2388.         dataReq.sg[0].addr = (Address)0xff905000;
  2389.         dataReq.sg[0].length = 100;
  2390.         if (ioctlPtr->command == IOC_HPPI_CONNECTION_SEND) {
  2391.         status = Net_HppiSendData (connPtr, &dataReq);
  2392.         } else {
  2393.         status = Net_HppiReceiveData (connPtr, &dataReq);
  2394.         }
  2395.         if (status != SUCCESS) {
  2396.         printf ("HPPI_CONNECTION_xfer: couldn't transfer 0x%x\n",
  2397.             status);
  2398.         return (FAILURE);
  2399.         }
  2400.         if (netHppiDebug) {
  2401.         printf ("HPPI_CONNECTION_xfer: waiting...\n");
  2402.         }
  2403.         MASTER_LOCK (&(interPtr->mutex));
  2404.         Sync_MasterWait(&dataDone, &(interPtr->mutex), FALSE);
  2405.         MASTER_UNLOCK (&(interPtr->mutex));
  2406.         if (netHppiDebug) {
  2407.         printf ("HPPI_CONNECTION_xfer: returned from wait.\n");
  2408.         }
  2409.         conn.status = connPtr->status;
  2410.         inSize = outSize = sizeof (Net_HppiConnection);
  2411.         fmtStatus = Fmt_Convert("w9", mach_Format, &inSize,
  2412.                     (Address)&conn, ioctlPtr->format,
  2413.                     &outSize, ioctlPtr->outBuffer);
  2414.         if (fmtStatus != FMT_OK) {
  2415.         printf("Return format HPPI_CONNECTION_xfer failed, 0x%x\n",
  2416.             fmtStatus);
  2417.         return GEN_INVALID_ARG;
  2418.         }
  2419.         status = dataReq.status;
  2420.         break;
  2421.     }
  2422.     case IOC_HPPI_IOP_OUTPUT: {
  2423.         int ioSize;
  2424.  
  2425.         inSize = outSize = sizeof (ioSize);
  2426.         fmtStatus = Fmt_Convert ("w", ioctlPtr->format, &inSize,
  2427.                      (Address)ioctlPtr->inBuffer,
  2428.                      mach_Format, &outSize, (Address)&ioSize);
  2429.         if (fmtStatus != FMT_OK) {
  2430.         printf("Format of IOC_HPPI_IOP_OUTPUT size failed, 0x%x\n",
  2431.             fmtStatus);
  2432.         return GEN_INVALID_ARG;
  2433.         }
  2434.         MASTER_LOCK (&interPtr->mutex);
  2435.         statePtr->flags |= NET_HPPI_STATE_IOP_OUTPUT_TEST;
  2436.         NetHppiLoopback (statePtr, ioSize, iopOutputCallback,
  2437.                  (ClientData)statePtr, 0);
  2438.         Sync_MasterWait (&iopOutputDone, &(interPtr->mutex), TRUE);
  2439.         MASTER_UNLOCK (&interPtr->mutex);
  2440.     }
  2441.     default: {
  2442.         printf("NetHppiIOControl: unknown ioctl 0x%x\n",
  2443.         ioctlPtr->command);
  2444.     }
  2445.  
  2446.     }
  2447.     return status;
  2448. }
  2449.  
  2450. /*
  2451.  *----------------------------------------------------------------------
  2452.  *
  2453.  * NetHppiSendReq --
  2454.  *
  2455.  *    Queue up a request for the adapter board. If there isn't
  2456.  *    any room in the queue then we block until there is.
  2457.  *
  2458.  * Results:
  2459.  *    Standard Sprite return status.
  2460.  *
  2461.  * Side effects:
  2462.  *    The adapter board is notified of the addition to the queue.
  2463.  *
  2464.  *----------------------------------------------------------------------
  2465.  */
  2466.  
  2467. ReturnStatus
  2468. NetHppiSendReq(statePtr, doneProc, data, rpc, scatterLength, scatterPtr, 
  2469.     requestSize, requestPtr)
  2470.     NetHppiState    *statePtr;    /* State of the adapter. */
  2471.     void        (*doneProc)();    /* Procedure to call when
  2472.                      * XRB is done. */
  2473.     ClientData        data;        /* Data used by doneProc. */
  2474.     Boolean        rpc;        /* Is this an RPC packet? */
  2475.     int            scatterLength;    /* Size of scatter/gather array. */
  2476.     Net_ScatterGather    *scatterPtr;    /* The scatter/gather array. */
  2477.     int            requestSize;    /* Size of the request. */
  2478.     NetUltraRequest    *requestPtr;    /* Request to be sent. */
  2479. {
  2480.     NetUltraXRB            *xrbPtr;
  2481.     NetUltraRequestHdr        *hdrPtr;
  2482.     NetUltraDMAInfo        *dmaPtr;
  2483.     ReturnStatus        status = SUCCESS;
  2484.     int                signal;
  2485.     NetUltraXRBInfo        *infoPtr;
  2486.     NetUltraTraceInfo        *tracePtr;
  2487.     int                size;
  2488.     int                i;
  2489.     Dev_HppiScatterGather    sgList;
  2490.     Dev_HppiOutput        outputCommand;
  2491.  
  2492.     if (netHppiDebug) {
  2493.     printf("NetHppiSendReq: sending a request\n");
  2494.     }
  2495.     xrbPtr = statePtr->nextToAdapterPtr;
  2496.  
  2497. #ifndef CLEAN
  2498.     if (netHppiTrace) {
  2499.     NEXT_TRACE (statePtr, &tracePtr);
  2500.     tracePtr->event = SEND_REQ;
  2501.     tracePtr->index = xrbPtr - statePtr->firstToAdapterPtr;
  2502.     Timer_GetCurrentTicks (&tracePtr->ticks);
  2503.     }
  2504.  
  2505. #endif
  2506.  
  2507.     /*
  2508.      * For the HPPI boards, the next xrb should never be filled, but
  2509.      * we'll leave the code in case we can DMA request blocks to the
  2510.      * adapter in the future.
  2511.      */
  2512.     if (statePtr->nextToAdapterPtr->filled) {
  2513.     do {
  2514.         if (netHppiDebug) {
  2515.         printf("NetHppiSendReq: no XRB free, waiting\n");
  2516.         }
  2517.         statePtr->toAdapterAvail.waiting = TRUE;
  2518.         signal = Sync_SlowMasterWait(
  2519.             (unsigned int) &statePtr->toAdapterAvail,
  2520.             &statePtr->interPtr->mutex, TRUE);
  2521.         if (signal) {
  2522.         return GEN_ABORTED_BY_SIGNAL;
  2523.         }
  2524.     } while(statePtr->nextToAdapterPtr->filled);
  2525.     }
  2526.     xrbPtr = statePtr->nextToAdapterPtr;
  2527.     hdrPtr = (NetUltraRequestHdr *) requestPtr;
  2528.     infoPtr = (NetUltraXRBInfo *) List_First(statePtr->freeXRBInfoList);
  2529.     if ((List_Links *) infoPtr == statePtr->freeXRBInfoList) {
  2530.     panic("NetHppiSendReq: no available XRBInfo structures!");
  2531.     }
  2532.     List_Remove((List_Links *) infoPtr);
  2533.     List_Insert((List_Links *) infoPtr, 
  2534.     LIST_ATFRONT(statePtr->pendingXRBInfoList));
  2535.     infoPtr->doneProc = doneProc;
  2536.     infoPtr->doneData = data;
  2537.     infoPtr->xrbPtr = xrbPtr;
  2538.     infoPtr->scatterPtr = scatterPtr;
  2539.     infoPtr->scatterLength = scatterLength;
  2540.     infoPtr->requestSize = requestSize;
  2541.     infoPtr->requestPtr = (union NetUltraRequest *) requestPtr;
  2542.     infoPtr->flags = NET_ULTRA_INFO_PENDING;
  2543.  
  2544. #if 0
  2545.     hdrPtr->infoPtr = infoPtr;
  2546. #else
  2547.     hdrPtr->infoPtr = (NetUltraXRBInfo *)infoPtr->requestTag;
  2548.     statePtr->tagToXRBInfo[infoPtr->requestTag] = infoPtr;
  2549. #endif
  2550.     hdrPtr->status = 0;
  2551.     hdrPtr->reference = 0;
  2552.  
  2553.     if (scatterLength > 0) {
  2554.     Address        buffer;
  2555.     List_Links    *itemPtr;
  2556.     /*
  2557.      * If the buffer is not in DVMA space then get one that is.
  2558.      */
  2559.     if (! DVMA_ADDRESS(scatterPtr[0].bufAddr, statePtr)) {
  2560.         if (netHppiDebug) {
  2561.         printf("Data is not in DVMA space.\n");
  2562.         }
  2563.         while(List_IsEmpty(statePtr->freeBufferList)) {
  2564.         int        signal;
  2565.         statePtr->bufferAvail.waiting = TRUE;
  2566.         signal = Sync_SlowMasterWait(
  2567.             (unsigned int) &statePtr->bufferAvail,
  2568.             &statePtr->interPtr->mutex, TRUE);
  2569.         if (signal) {
  2570.             status = GEN_ABORTED_BY_SIGNAL;
  2571.             goto exit;
  2572.         }
  2573.         }
  2574.         itemPtr = List_First(statePtr->freeBufferList);
  2575.         if (itemPtr == statePtr->freeBufferList) {
  2576.         panic("NetHppiSendReq: list screwup\n");
  2577.         }
  2578.         List_Remove(itemPtr);
  2579.         buffer = (Address) itemPtr;
  2580.         infoPtr->flags |= NET_ULTRA_INFO_STD_BUFFER;
  2581.         if (rpc) {
  2582.         int    lastIndex;
  2583.         /*
  2584.          * This is a standard RPC packet with 4 parts --
  2585.          * packet header, RPC header, RPC params, and data. 
  2586.          * Copy the first three into the DVMA buffer.  If the data
  2587.          * is below a threshold then copy it also.  Otherwise
  2588.          * map the data into DVMA space and remap the first three parts
  2589.          * so that they precede the data.
  2590.          */
  2591.         size = 0;
  2592.         lastIndex = scatterLength - 1;
  2593.         for (i = 0; i < scatterLength; i++) {
  2594.             size += scatterPtr[i].length;
  2595.         }
  2596.         Net_GatherCopy(scatterPtr, scatterLength, buffer);
  2597.         } else {
  2598.  
  2599.         if (netHppiDebug) {
  2600.             printf("Copying data into DVMA space.\n");
  2601.         }
  2602.         Net_GatherCopy(scatterPtr, 1, buffer);
  2603.         size = scatterPtr[0].length;
  2604.         }
  2605.     } else {
  2606.         /* 
  2607.          * The data is already in DVMA space.  It had better be contiguous!
  2608.          */
  2609.         if (netHppiDebug) {
  2610.         printf("Data is already in DVMA space.\n");
  2611.         }
  2612.         buffer = scatterPtr[0].bufAddr;
  2613.         size = scatterPtr[0].length;
  2614.     }
  2615.     if (! DVMA_ADDRESS(buffer, statePtr)) {
  2616.         buffer = BUFFER_TO_DVMA(buffer, statePtr);
  2617.     }
  2618.     hdrPtr->buffer = DVMA_TO_VME(buffer, statePtr);
  2619.     hdrPtr->size = size;
  2620.     sgList.size = 1;
  2621.     sgList.element[0].address = (uint32)DVMA_TO_VME(buffer, statePtr);
  2622.     sgList.element[0].size = size;
  2623.     } else {
  2624.     hdrPtr->size = 0;
  2625.     sgList.size = 0;
  2626.     }
  2627.  
  2628.     if ((statePtr->flags & NET_HPPI_STATE_STATS) &&
  2629.     (hdrPtr->cmd == NET_ULTRA_DGRAM_SEND_REQ)) {
  2630.     statePtr->stats.packetsSent += 1;
  2631.     statePtr->stats.bytesSent += hdrPtr->size;
  2632.     statePtr->stats.sentHistogram[hdrPtr->size >> 10] += 1;
  2633.     }
  2634.  
  2635.     dmaPtr = &xrbPtr->dma;
  2636.  
  2637.     if (hdrPtr->cmd == NET_ULTRA_DGRAM_SEND_REQ) {
  2638.     dmaPtr->cmd = NET_ULTRA_DMA_CMD_XRB_DATA;
  2639.     statePtr->numWritePending++;
  2640.     if (statePtr->numWritePending > statePtr->maxWritePending) {
  2641.         panic("NetHppiSendReq: too many writes.\n");
  2642.     }
  2643.     } else if (hdrPtr->cmd == NET_ULTRA_DGRAM_RECV_REQ) {
  2644.     dmaPtr->cmd = NET_ULTRA_DMA_CMD_XRB;
  2645.     statePtr->numReadPending++;
  2646.     if (statePtr->numReadPending > statePtr->maxReadPending) {
  2647.         panic("NetHppiSendReq: too many reads.\n");
  2648.     }
  2649.     } else {
  2650.     dmaPtr->cmd = NET_ULTRA_DMA_CMD_XRB;
  2651.     }
  2652.  
  2653. #if 0
  2654.     bcopy((char *) requestPtr, (char *) &xrbPtr->request, requestSize);
  2655. #endif
  2656.     /*
  2657.      * The channel-based adapters require the command to also be
  2658.      * stuffed into the transaction ID in the DMA word.
  2659.      */
  2660.     dmaPtr->id = hdrPtr->cmd;
  2661.     dmaPtr->reference = 0;
  2662.     dmaPtr->length = requestSize;
  2663.     sgList.tag = (int)hdrPtr->infoPtr;
  2664.     dmaPtr->infoPtr = hdrPtr->infoPtr;
  2665.     if (netHppiDebug) {
  2666.     printf ("NetHppiSendReq: tag is 0x%x\n", sgList.tag);
  2667.     }
  2668.     dmaPtr->offset = 0;
  2669.     /*
  2670.      * Set the filled field so the adapter will process the XRB.
  2671.      */
  2672.     xrbPtr->filled = 1;
  2673.     if (statePtr->nextToAdapterPtr == statePtr->lastToAdapterPtr) {
  2674.     statePtr->nextToAdapterPtr = statePtr->firstToAdapterPtr;
  2675.     } else {
  2676.     statePtr->nextToAdapterPtr++;
  2677.     }
  2678.  
  2679.     /*
  2680.      * Send the command to the adapter.  First, send the scatter-gather
  2681.      * list to the destination board.  Next, send the request to the
  2682.      * source board.
  2683.      */
  2684.     if (netHppiTrace) {
  2685.     sgList.hdr.opcode = DEV_HPPI_SCATTER_GATHER_TRACE;
  2686.     outputCommand.hdr.opcode = DEV_HPPI_OUTPUT_TRACE;
  2687.     } else {
  2688.     sgList.hdr.opcode = DEV_HPPI_SCATTER_GATHER;
  2689.     outputCommand.hdr.opcode = DEV_HPPI_OUTPUT;
  2690.     }
  2691.     outputCommand.hdr.magic = DEV_HPPI_SRC_MAGIC;
  2692.     outputCommand.fifoDataSize = dmaPtr->length + sizeof (*dmaPtr);
  2693.     outputCommand.iopDataSize = 0;
  2694.     outputCommand.hdr.magic = DEV_HPPI_SRC_MAGIC;
  2695.     if (netHppiDebug) {
  2696.     printf("NetHppiSendReq: xrbPtr = 0x%x, sending %d bytes\n", xrbPtr,
  2697.            outputCommand.fifoDataSize);
  2698.     }
  2699.     if (scatterLength > 0) {
  2700.     size = sizeof (sgList.hdr)+sizeof (sgList.size)+sizeof (sgList.tag) +
  2701.         sizeof (Dev_HppiScatterGatherElement) * sgList.size;
  2702.     sgList.hdr.magic = DEV_HPPI_DEST_MAGIC;
  2703.     NetHppiSendCmd (statePtr, size, (Address)&sgList, 0);
  2704.     }
  2705.  
  2706.     status = NetHppiSendCmd (statePtr, sizeof (outputCommand),
  2707.                  (Address)&outputCommand,
  2708.                  NET_HPPI_KEEP_SRC_FIFO | NET_HPPI_SRC_CMD);
  2709.     if (status != SUCCESS) {
  2710.     goto exit;
  2711.     }
  2712.     status = NetHppiCopyToFifo (dmaPtr, sizeof (*dmaPtr), statePtr,
  2713.                 NET_HPPI_SRC_CMD);
  2714.     if (status != SUCCESS) {
  2715.     goto exit;
  2716.     }
  2717.     status = NetHppiCopyToFifo (requestPtr, requestSize, statePtr,
  2718.                 NET_HPPI_SRC_CMD);
  2719.     if (status != SUCCESS) {
  2720.     goto exit;
  2721.     }
  2722.     if (hdrPtr->cmd == NET_ULTRA_DGRAM_SEND_REQ) {
  2723.     outputCommand.fifoDataSize = hdrPtr->size;
  2724.     status = NetHppiSendCmd (statePtr, sizeof (outputCommand),
  2725.                  (Address)&outputCommand,
  2726.                  NET_HPPI_KEEP_SRC_FIFO | NET_HPPI_SRC_CMD);
  2727.     if (status != SUCCESS) {
  2728.         goto exit;
  2729.     }
  2730.     for (i = 0; i < sgList.size; i++) {
  2731.         status=NetHppiCopyToFifo (VME_TO_BUFFER(sgList.element[i].address,
  2732.                          statePtr), sgList.element[i].size,
  2733.                    statePtr, NET_HPPI_SRC_CMD);
  2734.         if (status != SUCCESS) {
  2735.         goto exit;
  2736.         }
  2737.     }
  2738.     }
  2739.  
  2740. exit:
  2741.     /*
  2742.      * Since we just sent the XRB to the HPPI boards, it is no longer
  2743.      * filled.  The code still acts like it is DMAed out (with filled
  2744.      * flags, etc.) so that it can be easily modified in the future if
  2745.      * the HPPI boards DMA requests out of memory at some future date.
  2746.      */
  2747.     xrbPtr->filled = 0;
  2748.     NetHppiReleaseSrcFifo (statePtr);
  2749.     return status;
  2750. }
  2751.  
  2752. /*
  2753.  *----------------------------------------------------------------------
  2754.  *
  2755.  * InitQueues --
  2756.  *
  2757.  *    Initializes the XRB queues.
  2758.  *
  2759.  * Results:
  2760.  *    None.
  2761.  *
  2762.  * Side effects:
  2763.  *    Memory is allocated and mapped into DMA space if necessary.
  2764.  *
  2765.  *----------------------------------------------------------------------
  2766.  */
  2767.  
  2768. static void
  2769. InitQueues(statePtr)
  2770.     NetHppiState    *statePtr;    /* State of the adapter. */
  2771. {
  2772.     int        size;
  2773.     Address    addr;
  2774.     List_Links    *itemPtr;
  2775.     int        i;
  2776.  
  2777.     if (!(statePtr->queuesInit)) {
  2778.     /*
  2779.      * Allocate XRBs that go from the adapter to the host. 
  2780.      */
  2781.     size = sizeof(NetUltraXRB) * NET_HPPI_NUM_TO_HOST;
  2782. #ifdef QUEUES_IN_DUALPORT_RAM
  2783.     statePtr->firstToHostVME = (Address)NET_HPPI_DUAL_PORT_RAM;
  2784.     statePtr->firstToAdapterVME = (Address) NET_HPPI_DUAL_PORT_RAM + size;
  2785.     addr = VmMach_MapInDevice (statePtr->firstToHostVME, 3);
  2786. #else
  2787.     addr = (Address) malloc(size);
  2788.     addr = VmMach_DMAAlloc(size, (Address) addr);
  2789.     if (addr == (Address) NIL) {
  2790.         panic("NetUltraInit: unable to allocate DMA space.\n");
  2791.     }
  2792.     statePtr->firstToHostVME = DVMA_TO_VME (addr, statePtr);
  2793. #endif
  2794.     statePtr->firstToHostPtr = (NetUltraXRB *) addr;
  2795.     /* 
  2796.      * Allocate XRBs that go from the host to the adapter. 
  2797.      */
  2798.     size = sizeof(NetUltraXRB) * NET_HPPI_NUM_TO_ADAPTER;
  2799.  
  2800. #ifdef QUEUES_IN_DUALPORT_RAM
  2801.     addr = VmMach_MapInDevice (statePtr->firstToAdapterVME, 3);
  2802.     if (Mach_Probe (sizeof(int), addr + size, (Address)&i) == FAILURE) {
  2803.         panic ("NetHppiInit: circular queues too big.\n");
  2804.     }
  2805. #else
  2806.     addr = (Address) malloc(size);
  2807.     addr = VmMach_DMAAlloc(size, (Address) addr);
  2808.     if (addr == (Address) NIL) {
  2809.         panic("NetUltraInit: unable to allocate DMA space.\n");
  2810.     }
  2811.     statePtr->firstToAdapterVME = DVMA_TO_VME (addr, statePtr);
  2812. #endif
  2813.     statePtr->firstToAdapterPtr = (NetUltraXRB *) addr;
  2814.     statePtr->pendingXRBInfoList = &statePtr->pendingXRBInfoListHdr;
  2815.     statePtr->freeXRBInfoList = &statePtr->freeXRBInfoListHdr;
  2816.     List_Init(statePtr->pendingXRBInfoList);
  2817.     List_Init(statePtr->freeXRBInfoList);
  2818.     for (i = 0; i < NET_HPPI_NUM_TO_ADAPTER + NET_HPPI_NUM_TO_HOST; i++) {
  2819.         itemPtr = (List_Links *) malloc(sizeof(NetUltraXRBInfo));
  2820.         ((NetUltraXRBInfo *)itemPtr)->requestTag = i + 1;
  2821.         List_InitElement(itemPtr);
  2822.         List_Insert(itemPtr, LIST_ATREAR(statePtr->freeXRBInfoList));
  2823.     }
  2824.     /*
  2825.      * Allocate buffers in DVMA space for pending reads and writes. 
  2826.      */
  2827.     statePtr->maxReadPending = NET_HPPI_PENDING_READS;
  2828.     statePtr->numReadPending = 0;
  2829.     statePtr->maxWritePending = NET_HPPI_PENDING_WRITES;
  2830.     statePtr->numWritePending = 0;
  2831.     statePtr->numBuffers = statePtr->maxReadPending + 
  2832.         statePtr->maxWritePending;
  2833.     statePtr->bufferSize = NET_HPPI_MAX_BYTES;
  2834.     size = statePtr->numBuffers * statePtr->bufferSize;
  2835. #if 1
  2836.     addr = (Address) malloc(size);
  2837.     statePtr->buffers = addr;
  2838.     addr = VmMach_DMAAlloc(size, (Address) addr);
  2839.     statePtr->buffersDVMA = addr;
  2840. #else
  2841.     addr = NET_HPPI_DUAL_PORT_RAM + 0x4000;
  2842. #endif
  2843.  
  2844.     statePtr->freeBufferList = &statePtr->freeBufferListHdr;
  2845.  
  2846.     statePtr->queuesInit = TRUE;
  2847.     }
  2848.     statePtr->lastToHostPtr = statePtr->firstToHostPtr + 
  2849.         NET_HPPI_NUM_TO_HOST - 1;
  2850.     statePtr->nextToHostPtr = statePtr->firstToHostPtr;
  2851.     statePtr->lastToAdapterPtr = statePtr->firstToAdapterPtr + 
  2852.         NET_HPPI_NUM_TO_ADAPTER - 1;
  2853.     statePtr->nextToAdapterPtr = statePtr->firstToAdapterPtr;
  2854.     size = sizeof(NetUltraXRB) * NET_HPPI_NUM_TO_HOST;
  2855.     bzero((char *) statePtr->firstToHostPtr, size);
  2856.     size = sizeof(NetUltraXRB) * NET_HPPI_NUM_TO_ADAPTER;
  2857.     bzero((char *) statePtr->firstToAdapterPtr, size);
  2858.     while (!List_IsEmpty(statePtr->pendingXRBInfoList)) {
  2859.     itemPtr = List_First(statePtr->pendingXRBInfoList);
  2860.     List_Remove(itemPtr);
  2861.     List_Insert(itemPtr, LIST_ATREAR(statePtr->freeXRBInfoList));
  2862.     }
  2863.     bzero((char *) statePtr->buffers, statePtr->numBuffers * 
  2864.     statePtr->bufferSize);
  2865.     List_Init(statePtr->freeBufferList);
  2866.     for (i = 0; i < statePtr->numBuffers; i++) {
  2867.     itemPtr = (List_Links *) 
  2868.         (statePtr->buffers + (i * statePtr->bufferSize));
  2869.     List_InitElement(itemPtr);
  2870.     List_Insert(itemPtr, LIST_ATREAR(statePtr->freeBufferList));
  2871.     }
  2872.     for (i = 0; i < NET_HPPI_MAX_TAGS; i++) {
  2873.     statePtr->tags[i] = 0;
  2874.     }
  2875.     statePtr->curSgTag = 1;
  2876.     for (i = 0; i < NET_HPPI_MAX_CONNECTIONS; i++) {
  2877.     statePtr->connection[i].flags = 0;
  2878.     statePtr->connection[i].statePtr = statePtr;
  2879.     }
  2880. }
  2881.  
  2882. /*
  2883.  *----------------------------------------------------------------------
  2884.  *
  2885.  * NetHppiStart--
  2886.  *
  2887.  *    Send a start request to the adapter.
  2888.  *    Assumes the interface mutex is held.
  2889.  *
  2890.  * Results:
  2891.  *    Standard Sprite return status.
  2892.  *
  2893.  * Side effects:
  2894.  *    A start request is sent to the board.
  2895.  *
  2896.  *----------------------------------------------------------------------
  2897.  */
  2898.  
  2899. ReturnStatus
  2900. NetHppiStart(statePtr)
  2901.     NetHppiState    *statePtr;    /* State of the adapter. */
  2902. {
  2903.     NetUltraRequest        request;
  2904.     NetUltraStartRequest    *startPtr;
  2905.     NetUltraRequestHdr        *hdrPtr;
  2906.     Net_Interface        *interPtr;
  2907.     int                i;
  2908.     int                power = 0;
  2909.     int                tmp;
  2910.     ReturnStatus        status = SUCCESS;
  2911.     static int            sequence = 0;
  2912.     Sync_Condition        startComplete;
  2913.  
  2914.     interPtr = statePtr->interPtr;
  2915.     startPtr = &request.start;
  2916.     hdrPtr = &startPtr->hdr;
  2917.     if (!Net_AddrCmp(&interPtr->netAddress[NET_PROTO_RAW], &netZeroAddress)) {
  2918.     printf("NetHppiStart: can't send start cmd-adapter address not set\n");
  2919.     status = FAILURE;
  2920.     goto exit;
  2921.     }
  2922.     if (statePtr->flags & NET_HPPI_STATE_START) {
  2923.     printf("NetHppiStart: adapter already started.\n");
  2924.     status = FAILURE;
  2925.     goto exit;
  2926.     } else if (statePtr->flags &
  2927.            (NET_HPPI_STATE_SRC_EPROM | NET_HPPI_STATE_DST_EPROM)) {
  2928.     printf ("NetHppiStart: boards not yet set up.\n");
  2929.     status = FAILURE;
  2930.     goto exit;
  2931.     }
  2932.     bzero((char *) &request, sizeof(request));
  2933.     hdrPtr->cmd = NET_ULTRA_NEW_START_REQ;
  2934.     startPtr->sequence = sequence;
  2935.     sequence++;
  2936.     startPtr->hostType = NET_ULTRA_START_HOSTTYPE_SUN;
  2937.     startPtr->adapterType = NET_ULTRA_START_ADAPTYPE_HSC;
  2938.     /*
  2939.      * Determine which power of 2 equals the maximum packet size. 
  2940.      */
  2941.     tmp = interPtr->maxBytes;
  2942.     for (i = 0; i < sizeof(int) * 8; i++) {
  2943.     if (tmp & 1) {
  2944.         power = i;
  2945.     }
  2946.     tmp >>= 1;
  2947.     }
  2948.     if (1 << power > interPtr->maxBytes) {
  2949.     power++;
  2950.     }
  2951.     startPtr->hostMaxBytes = power;
  2952.     if (netHppiDebug) {
  2953.     printf ("NetHppiStart: power = %d\n", power);
  2954.     }
  2955.     /* 
  2956.      * This part is kind of goofy.  The adapter expects the network
  2957.      * address to be 7 bytes long (the first byte is missing). We have
  2958.      * to bcopy the netAddress minus its first byte.
  2959.      */
  2960.     startPtr->netAddressSize = 7;
  2961. #if 0
  2962.     bcopy(&(((char *) &interPtr->netAddress[NET_PROTO_RAW])[1]),
  2963.     (char *) &startPtr->netAddressBuf, sizeof(Net_UltraAddress)-1);
  2964. #endif
  2965.     bcopy ((char *)&(interPtr->netAddress[NET_PROTO_RAW].address.ultra) + 1,
  2966.        startPtr->netAddressBuf, startPtr->netAddressSize);
  2967.     startPtr->netAddressBuf[0] = 0x49;
  2968.     startPtr->netAddressBuf[5] = 0xfe;
  2969.     status = NetHppiSendReq(statePtr, StandardDone, 
  2970.         (ClientData) &startComplete, FALSE, 
  2971.         0, (Net_ScatterGather *) NIL, sizeof(NetUltraStartRequest), 
  2972.         &request);
  2973.     if (status != SUCCESS) {
  2974.     printf("NetHppiStart: unable to send start request\n");
  2975.     goto exit;
  2976.     }
  2977.     Sync_MasterWait(&(startComplete), &(interPtr->mutex), FALSE);
  2978.     if (netHppiDebug) {
  2979.     printf ("NetHppiStart: returned from wait\n");
  2980.     }
  2981.     if (hdrPtr->status & NET_ULTRA_STATUS_OK) {
  2982.     if (netHppiDebug) {
  2983.         printf("NetHppiStart: hdrPtr->status = %d : %s\n",
  2984.         hdrPtr->status, GetStatusString(hdrPtr->status));
  2985.     }
  2986.     if (netHppiDebug) {
  2987.         printf("Ultranet hub started\n");
  2988.         printf("Ucode %d\n", startPtr->ucodeRel);
  2989.         printf("Adapter type %d, adapter hw %d\n", startPtr->adapterType,
  2990.         startPtr->adapterHW);
  2991.         printf("Max VC = %d\n", startPtr->maxVC);
  2992.         printf("Max DRCV = %d\n", startPtr->maxDRCV);
  2993.         printf("Max DSND = %d\n", startPtr->maxDSND);
  2994.         printf("Slot = %d\n", startPtr->slot);
  2995.         printf("Speed = %d\n", startPtr->speed);
  2996.         printf("Max bytes = %d\n", (1 << startPtr->adapterMaxBytes));
  2997.     }
  2998.     if (startPtr->maxDRCV < statePtr->maxReadPending) {
  2999.         printf("NetHppiStart: WARNING: max pending reads reset to %d\n",
  3000.         startPtr->maxDRCV);
  3001.         statePtr->maxReadPending = startPtr->maxDRCV;
  3002.     }
  3003.     if (startPtr->maxDSND < statePtr->maxWritePending) {
  3004.         printf("NetUltraStart: WARNING: max pending writes reset to %d\n",
  3005.         startPtr->maxDSND);
  3006.         statePtr->maxWritePending = startPtr->maxDSND;
  3007.     }
  3008.     if (startPtr->adapterMaxBytes < power) {
  3009.         interPtr->maxBytes = 1 << power;
  3010.         printf("NetUltraStart: WARNING: max bytes reset to %d\n",
  3011.         interPtr->maxBytes);
  3012.     }
  3013.     statePtr->maxBytesPower = startPtr->adapterMaxBytes;
  3014.     statePtr->flags |= NET_HPPI_STATE_START;
  3015.     } else {
  3016.     printf("NetHppiStart: start command failed <0x%x> : %s\n",
  3017.         hdrPtr->status, GetStatusString(hdrPtr->status));
  3018.     }
  3019.  
  3020. exit:
  3021.     return status;
  3022. }
  3023.  
  3024. /*
  3025.  *----------------------------------------------------------------------
  3026.  *
  3027.  * NetHppiStop--
  3028.  *
  3029.  *    Send a stop request to the board.
  3030.  *    Assumes the interface mutex is held.
  3031.  *
  3032.  * Results:
  3033.  *    Standard Sprite return status.
  3034.  *
  3035.  * Side effects:
  3036.  *    The adapter abandons what it is doing.
  3037.  *
  3038.  *----------------------------------------------------------------------
  3039.  */
  3040.  
  3041. ReturnStatus
  3042. NetHppiStop(statePtr)
  3043.     NetHppiState    *statePtr;    /* State of the adapter. */
  3044. {
  3045.     NetUltraRequest        request;
  3046.     NetUltraStopRequest        *stopPtr;
  3047.     NetUltraRequestHdr        *hdrPtr;
  3048.     Net_Interface        *interPtr;
  3049.     ReturnStatus        status = SUCCESS;
  3050.     Sync_Condition        stopComplete;
  3051.  
  3052.     interPtr = statePtr->interPtr;
  3053.     stopPtr = &request.stop;
  3054.     hdrPtr = &stopPtr->hdr;
  3055.     if (!(statePtr->flags & NET_HPPI_STATE_START)) {
  3056.     printf("NetHppiStop: adapter not started.\n");
  3057.     status = FAILURE;
  3058.     goto exit;
  3059.     }
  3060.     bzero((char *) &request, sizeof(request));
  3061.     hdrPtr->cmd = NET_ULTRA_STOP_REQ;
  3062.     status = NetHppiSendReq(statePtr, StandardDone, 
  3063.         (ClientData) &stopComplete, FALSE,
  3064.         0, (Net_ScatterGather *) NIL, sizeof(NetUltraStopRequest), 
  3065.         &request);
  3066.     if (status != SUCCESS) {
  3067.     printf("NetHppiStop: unable to send stop request\n");
  3068.     goto exit;
  3069.     }
  3070.     Sync_MasterWait(&(stopComplete), &(interPtr->mutex), FALSE);
  3071.     if (hdrPtr->status & NET_ULTRA_STATUS_OK) {
  3072.     if (netHppiDebug) {
  3073.         printf("NetHppiStop: hdrPtr->status = %d : %s\n",
  3074.         hdrPtr->status, GetStatusString(hdrPtr->status));
  3075.     }
  3076.     statePtr->flags &= ~NET_HPPI_STATE_START;
  3077.     } else {
  3078.     printf("NetHppiStop: stop command failed <0x%x> : %s\n",
  3079.         hdrPtr->status, GetStatusString(hdrPtr->status));
  3080.     }
  3081. exit:
  3082.     return status;
  3083. }
  3084.  
  3085. /*
  3086.  *----------------------------------------------------------------------
  3087.  *
  3088.  * NetHppiSendDgram --
  3089.  *
  3090.  *    This routine will send a datagram to the specified host.  It
  3091.  *    is intended for debugging purposes.  
  3092.  *
  3093.  * Results:
  3094.  *    None.
  3095.  *
  3096.  * Side effects:
  3097.  *    A write is queued to the adapter.
  3098.  *
  3099.  *----------------------------------------------------------------------
  3100.  */
  3101.  
  3102. static ReturnStatus
  3103. NetHppiSendDgram(interPtr, netAddressPtr, count, bufSize, buffer, timePtr)
  3104.     Net_Interface    *interPtr;        /* Interface to send on. */
  3105.     Net_Address        *netAddressPtr;        /* Host to send to. */
  3106.     int            count;            /* Number of times to send
  3107.                          * datagram. */
  3108.     int            bufSize;        /* Size of data buffer. */
  3109.     Address        buffer;            /* Data to send. */
  3110.     Time        *timePtr;        /* Place to store total 
  3111.                          * time to send datagrams. */
  3112. {
  3113.     NetHppiState        *statePtr;
  3114.     ReturnStatus        status;
  3115.     Timer_Ticks         startTime;
  3116.     Timer_Ticks         endTime;
  3117.     Dev_HppiSendDSND        dgramCmd;
  3118.  
  3119.     MASTER_LOCK(&interPtr->mutex);
  3120.     if (netHppiDebug) {
  3121.     char    address[100];
  3122.     (void) Net_AddrToString(netAddressPtr, address);
  3123.     printf("NetHppiSendDgram: sending %d bytes to %s\n", bufSize, address);
  3124.     }
  3125.     statePtr = (NetHppiState *) interPtr->interfaceData;
  3126.     if (!(statePtr->flags & NET_HPPI_STATE_START)) {
  3127.     printf("NetHppiSendDgram: adapter not started!\n");
  3128.     status = FAILURE;
  3129.     goto exit;
  3130.     }
  3131.     bzero((char *) &dgramCmd, sizeof(dgramCmd));
  3132.     dgramCmd.hdr.opcode = DEV_HPPI_SEND_DSND;
  3133.     dgramCmd.xrbHdr.xrbId = (uint32)interPtr;
  3134.     dgramCmd.xrbHdr.xrbBufId = (uint32)&dgramCmd;
  3135.     bcopy ((char*)&(netAddressPtr->address.ultra)+1, &(dgramCmd.xrbRemTA),
  3136.        sizeof (dgramCmd.xrbRemTA));
  3137.     dgramCmd.xrbRemTA[0] = 0x49;
  3138.     dgramCmd.xrbRemTA[5] = 0xfe;
  3139.     bcopy ((char *)&(interPtr->netAddress[NET_PROTO_RAW].address.ultra) + 1,
  3140.        &(dgramCmd.xrbLocTA), sizeof (dgramCmd.xrbLocTA));
  3141.     dgramCmd.xrbLocTA[0] = 0x49;
  3142.     dgramCmd.xrbLocTA[5] = 0xfe;
  3143.     bcopy (statePtr->curTsap, dgramCmd.tsap, sizeof (dgramCmd.tsap));
  3144.  
  3145.     if (buffer == (Address)NIL) {
  3146.     buffer = statePtr->buffers;
  3147.     }
  3148.     dgramCmd.fifoDataSize = bufSize;
  3149.     dgramCmd.iopDataSize = 0;
  3150.     dgramCmd.xrbHdr.tag = 1;
  3151.     statePtr->flags |= NET_HPPI_STATE_DSND_TEST;
  3152.     statePtr->flags &= ~NET_HPPI_STATE_NORMAL;
  3153.     dsndCount = count;
  3154.     Timer_GetCurrentTicks(&startTime);
  3155.  
  3156.     status = NetHppiSendCmd (statePtr, sizeof (dgramCmd), (Address)&dgramCmd,
  3157.                  NET_HPPI_SRC_CMD);
  3158.     if (status != SUCCESS) {
  3159.     if (netHppiDebug) {
  3160.         printf ("NetHppiSendDgram: command failed 0x%x\n", status);
  3161.     }
  3162.     goto exit;
  3163.     }
  3164.     status = NetHppiCopyToFifo (buffer, bufSize, statePtr, NET_HPPI_SRC_CMD);
  3165.     if (status != SUCCESS) {
  3166.     if (netHppiDebug) {
  3167.         printf ("NetHppiSendDgram: data copy failed 0x%x\n", status);
  3168.     }
  3169.     goto exit;
  3170.     }
  3171.  
  3172.     if (netHppiDebug) {
  3173.     printf ("NetHppiSendDgram: waiting for dgram to return.\n");
  3174.     }
  3175.     Sync_MasterWait(&dsndTestDone, &(interPtr->mutex), FALSE);
  3176.     Timer_GetCurrentTicks(&endTime);
  3177. #ifndef CLEAN
  3178.     if (netHppiDebug) {
  3179.     printf("NetHppiSendDgram: test done.\n");
  3180.     } 
  3181. #endif
  3182.     statePtr->flags &= ~NET_HPPI_STATE_DSND_TEST;
  3183.     statePtr->flags |= NET_HPPI_STATE_NORMAL;
  3184.     Timer_SubtractTicks(endTime, startTime, &endTime);
  3185.     Timer_TicksToTime(endTime, timePtr);
  3186. exit:
  3187.     MASTER_UNLOCK(&interPtr->mutex);
  3188.     return status;
  3189. }
  3190.  
  3191. /*
  3192.  *----------------------------------------------------------------------
  3193.  *
  3194.  * DgramSendDone --
  3195.  *
  3196.  *    Called by the interrupt handler when the datagram sent by 
  3197.  *     NetUltraSendDgram is actually sent.
  3198.  *
  3199.  * Results:
  3200.  *    None.
  3201.  *
  3202.  * Side effects:
  3203.  *    The process waiting for the datagram to be sent is notified.
  3204.  *
  3205.  *----------------------------------------------------------------------
  3206.  */
  3207.  
  3208. static void
  3209. DgramSendDone(dgramCmdPtr)
  3210. Dev_HppiSendDSND*    dgramCmdPtr;
  3211. {
  3212.     if (!(dgramCmdPtr->xrbHdr.status & NET_ULTRA_STATUS_OK)) {
  3213.     printf ("DgramSendDone: dgram send failed 0x%x\n",
  3214.         dgramCmdPtr->xrbHdr.status);
  3215.     } else {
  3216. #ifndef CLEAN
  3217.     if (netHppiDebug) {
  3218.         printf("DgramSendDone: datagram sent ok\n");
  3219.     }
  3220. #endif
  3221.     }
  3222.  
  3223.     Sync_MasterBroadcast ((Sync_Condition *) &dsndTestDone);
  3224.  
  3225. #ifndef CLEAN
  3226.     if (netHppiDebug) {
  3227.     printf("DgramSendDone: returning.\n");
  3228.     }
  3229. #endif
  3230.  
  3231. }
  3232.  
  3233.  
  3234. /*
  3235.  *----------------------------------------------------------------------
  3236.  *
  3237.  * NetHppiRecvDgram --
  3238.  *
  3239.  *    This routine will receive a datagram.  The receive address is
  3240.  *    ignored, as is the buffer address (the link board memory will
  3241.  *    be used).  This is intended for debugging purposes, and is pretty
  3242.  *    slow.
  3243.  *
  3244.  * Results:
  3245.  *    None.
  3246.  *
  3247.  * Side effects:
  3248.  *    A read is queued to the adapter.
  3249.  *
  3250.  *----------------------------------------------------------------------
  3251.  */
  3252.  
  3253. static
  3254. void
  3255. NetHppiRecvDgram(interPtr)
  3256. Net_Interface    *interPtr;        /* Interface to send on. */
  3257. {
  3258.     int            bufSize;        /* Size of data buffer. */
  3259.     Address        buffer;            /* Data to send. */
  3260.     NetHppiState    *statePtr = (NetHppiState*)interPtr->interfaceData;
  3261.     ReturnStatus        status = SUCCESS;
  3262.     Timer_Ticks         startTime;
  3263.     Timer_Ticks         endTime;
  3264.     Dev_HppiSendDRCV        dgramCmd;
  3265.     Dev_HppiScatterGather    sgCmd;
  3266.     int                sgCmdSize;
  3267.  
  3268.     MASTER_LOCK(&interPtr->mutex);
  3269.     while ((statePtr->flags & NET_HPPI_STATE_SINK) && (status == SUCCESS)) {
  3270.     bufSize = 0x8000;
  3271.     buffer = (Address)NET_HPPI_DUAL_PORT_RAM + 0x8000;
  3272. #if 0
  3273.     if (netHppiDebug) {
  3274.         char    address[100];
  3275.         (void) Net_AddrToString(netAddressPtr, address);
  3276.         printf("NetHppiRecvDgram: receiving %d bytes\n", bufSize);
  3277.     }
  3278. #endif
  3279.     statePtr = (NetHppiState *) interPtr->interfaceData;
  3280.     if (!(statePtr->flags & NET_HPPI_STATE_START)) {
  3281.         printf("NetHppiRecvDgram: adapter not started!\n");
  3282.         status = FAILURE;
  3283.         goto exit;
  3284.     }
  3285.     /*
  3286.      * Send the scatter-gather array.  Use the link board memory to store
  3287.      * the return data.
  3288.      */
  3289.     sgCmd.size = 1;
  3290.     sgCmd.offset = 0;
  3291.     if ((sgCmd.tag = getSgTag (statePtr)) == -1) {
  3292.         printf ("NetHppiRecvDgram: couldn't get SG tag.\n");
  3293.         status = FAILURE;
  3294.         goto exit;
  3295.     }
  3296.     sgCmd.element[0].address = (uint32)buffer;
  3297.     sgCmd.element[0].size = (uint32)bufSize;
  3298.     sgCmd.hdr.opcode = DEV_HPPI_SCATTER_GATHER;
  3299.     sgCmdSize = (sizeof (sgCmd) - sizeof (sgCmd.element)) +
  3300.         (sgCmd.size * sizeof (sgCmd.element[0]));
  3301.     status = NetHppiSendCmd (statePtr, sgCmdSize, (Address)&sgCmd,
  3302.                  NET_HPPI_DST_CMD);
  3303.     if (status != SUCCESS) {
  3304.         printf ("NetHppiDgramRecv: SG command failed 0x%x\n", status);
  3305.         goto exit;
  3306.     }
  3307.     
  3308.     bzero((char *) &dgramCmd, sizeof(dgramCmd));
  3309.     dgramCmd.hdr.opcode = DEV_HPPI_SEND_DRCV;
  3310.     dgramCmd.xrbHdr.xrbId = (uint32)interPtr;
  3311.     dgramCmd.xrbHdr.xrbBufId = (uint32)&dgramCmd;
  3312.     dgramCmd.xrbHdr.tag = sgCmd.tag;
  3313.     bzero (&dgramCmd.xrbRemTA, sizeof (dgramCmd.xrbRemTA));
  3314.     bzero (&dgramCmd.xrbLocTA, sizeof (dgramCmd.xrbLocTA));
  3315.     bcopy (statePtr->curTsap, dgramCmd.tsap, sizeof (dgramCmd.tsap));
  3316. #if 0
  3317.     dgramCmd.xrbRemTA[1] = 0x49;
  3318.     dgramCmd.xrbRemTA[6] = 0xfe;
  3319.     dgramCmd.xrbLocTA[1] = 0x49;
  3320.     dgramCmd.xrbLocTA[6] = 0xfe;
  3321. #endif
  3322.     dgramCmd.cnt = bufSize;
  3323.     
  3324.     if (buffer == (Address)NIL) {
  3325.         buffer = statePtr->buffers;
  3326.     }
  3327.     Timer_GetCurrentTicks(&startTime);
  3328.     
  3329.     status = NetHppiSendCmd (statePtr, sizeof (dgramCmd),
  3330.                  (Address)&dgramCmd, NET_HPPI_SRC_CMD);
  3331.     if (status != SUCCESS) {
  3332.         if (netHppiDebug) {
  3333.         printf ("NetHppiRecvDgram: command failed 0x%x\n", status);
  3334.         }
  3335.         goto exit;
  3336.     }
  3337.     
  3338.     if (netHppiDebug) {
  3339.         printf ("NetHppiRecvDgram: waiting to receive dgram.\n");
  3340.     }
  3341.     Sync_MasterWait(&drcvTestDone, &(interPtr->mutex), FALSE);
  3342.     Timer_GetCurrentTicks(&endTime);
  3343. #ifndef CLEAN
  3344.     if (netHppiDebug) {
  3345.         printf("NetHppiRecvDgram: test done.\n");
  3346.     } 
  3347. #endif
  3348.     Timer_SubtractTicks(endTime, startTime, &endTime);
  3349. #if 0
  3350.     Timer_TicksToTime(endTime, timePtr);
  3351. #endif
  3352.       exit:
  3353.     ;
  3354.     }
  3355.     statePtr->flags &= ~NET_HPPI_STATE_SINK;
  3356.     MASTER_UNLOCK(&interPtr->mutex);
  3357. }
  3358.  
  3359. /*
  3360.  *----------------------------------------------------------------------
  3361.  *
  3362.  * DgramRecvDone --
  3363.  *
  3364.  *    Called by the interrupt handler when the datagram requested by
  3365.  *     NetUltraRecvDgram is actually received.
  3366.  *
  3367.  * Results:
  3368.  *    None.
  3369.  *
  3370.  * Side effects:
  3371.  *    The process waiting for the datagram to be received is notified.
  3372.  *
  3373.  *----------------------------------------------------------------------
  3374.  */
  3375.  
  3376. static void
  3377. DgramRecvDone(dgramCmdPtr)
  3378. Dev_HppiSendDRCV*    dgramCmdPtr;
  3379. {
  3380.     Net_Interface*    interPtr;
  3381.     NetHppiState*    statePtr;
  3382.  
  3383.     interPtr = (Net_Interface*)(dgramCmdPtr->xrbHdr.xrbId);
  3384.     statePtr = (NetHppiState*)(interPtr->interfaceData);
  3385.     if (!(dgramCmdPtr->xrbHdr.status & NET_ULTRA_STATUS_OK)) {
  3386.     printf ("DgramRecvDone: dgram recv failed (status=0x%x)\n",
  3387.         dgramCmdPtr->xrbHdr.status);
  3388.     printf ("DgramRecvDone: terminating datagram sinking...\n");
  3389.     MASTER_LOCK (&interPtr->mutex);
  3390.     statePtr->flags &= ~NET_HPPI_STATE_SINK;
  3391.     statePtr->flags |= NET_HPPI_STATE_NORMAL;
  3392.     MASTER_UNLOCK (&interPtr->mutex);
  3393.     } else {
  3394. #ifndef CLEAN
  3395.     if (netHppiDebug) {
  3396.         printf("DgramRecvDone: got datagram of size 0x%x\n",
  3397.            dgramCmdPtr->cnt);
  3398.     }
  3399. #endif
  3400.     }
  3401.  
  3402.     Sync_MasterBroadcast ((Sync_Condition *) &drcvTestDone);
  3403.  
  3404. #ifndef CLEAN
  3405.     if (netHppiDebug) {
  3406.     printf("DgramRecvDone: returning.\n");
  3407.     }
  3408. #endif
  3409.  
  3410. }
  3411.  
  3412.  
  3413. /*
  3414.  *----------------------------------------------------------------------
  3415.  *
  3416.  * NetHppiOutputStub --
  3417.  *
  3418.  *    Return FAILURE -- the network shouldn't be trying to output
  3419.  *    RPC packets.
  3420.  *
  3421.  *----------------------------------------------------------------------
  3422.  */
  3423. ReturnStatus
  3424. NetHppiOutputStub(interPtr, hdrPtr, scatterGatherPtr, scatterGatherLength,
  3425.           rpc, statusPtr)
  3426.     Net_Interface        *interPtr;    /* The interface to use. */
  3427.     Address            hdrPtr;        /* Packet header. */
  3428.     Net_ScatterGather        *scatterGatherPtr; /* Scatter/gather elems.*/
  3429.     int                scatterGatherLength; /* Number of elements in
  3430.                               * scatter/gather list. */
  3431.     Boolean            rpc;        /* Is this an RPC packet? */
  3432.     ReturnStatus        *statusPtr;    /* Place to store status. */
  3433. {
  3434.     printf ("NetHppiOutputStub: shouldn't call HPPI for normal output.\n");
  3435.     return FAILURE;
  3436. }
  3437.  
  3438. /*
  3439.  *----------------------------------------------------------------------
  3440.  *
  3441.  * NetHppiSource --
  3442.  *
  3443.  *    This routine will send a stream of datagrams to the specified host.
  3444.  *
  3445.  * Results:
  3446.  *    None.
  3447.  *
  3448.  * Side effects:
  3449.  *    A write is queued to the adapter.
  3450.  *
  3451.  *----------------------------------------------------------------------
  3452.  */
  3453.  
  3454. static ReturnStatus
  3455. NetHppiSource(interPtr, netAddressPtr, count, bufSize, buffer, timePtr)
  3456.     Net_Interface    *interPtr;        /* Interface to send on. */
  3457.     Net_Address        *netAddressPtr;        /* Host to send to. */
  3458.     int            count;            /* Number of times to send
  3459.                          * datagram. */
  3460.     int            bufSize;        /* Size of data buffer. */
  3461.     Address        buffer;            /* Data to send. */
  3462.     Time        *timePtr;        /* Place to store total 
  3463.                          * time to send datagrams. */
  3464. {
  3465.     NetHppiState        *statePtr;
  3466.     NetUltraRequest        request;
  3467.     NetUltraDatagramRequest    *dgramReqPtr;
  3468.     NetUltraRequestHdr        *hdrPtr;
  3469.     ReturnStatus        status = SUCCESS;
  3470.     Address            itemPtr;
  3471.     char            *ptr;
  3472.     Timer_Ticks         startTime;
  3473.     Timer_Ticks         endTime;
  3474.     Timer_Ticks         curTime;
  3475.     NetUltraTraceInfo        *tracePtr;
  3476.     Net_ScatterGather        scatter;
  3477.  
  3478.     MASTER_LOCK(&interPtr->mutex);
  3479. #ifndef CLEAN
  3480.     if (netHppiDebug) {
  3481.     char    address[100];
  3482.     (void) Net_AddrToString(netAddressPtr, address);
  3483.     printf("NetHppiSendDgram: sending to %s\n", address);
  3484.     }
  3485. #endif
  3486.     statePtr = (NetHppiState *) interPtr->interfaceData;
  3487.     bzero((char *) &request, sizeof(request));
  3488.     dgramReqPtr = &request.dgram;
  3489.     hdrPtr = &dgramReqPtr->hdr;
  3490.     dgramReqPtr->remoteAddress = wildcardAddress;
  3491.     dgramReqPtr->remoteAddress.tsapSize = 2;
  3492.     dgramReqPtr->remoteAddress.tsap[1] = 1;
  3493.     dgramReqPtr->remoteAddress.address = netAddressPtr->address.ultra;
  3494.     ptr = (char *) &dgramReqPtr->remoteAddress.address;
  3495.     ptr[1] = 0x49;
  3496.     ptr[6] = 0xfe;
  3497.     dgramReqPtr->localAddress = wildcardAddress;
  3498.     dgramReqPtr->localAddress.tsapSize = 2;
  3499.     dgramReqPtr->localAddress.tsap[1] = 1;
  3500.     dgramReqPtr->localAddress.address = 
  3501.     interPtr->netAddress[NET_PROTO_RAW].address.ultra;
  3502.     ptr = (char *) &dgramReqPtr->localAddress.address;
  3503.     ptr[1] = 0x49;
  3504.     ptr[6] = 0xfe;
  3505.     hdrPtr->cmd = NET_ULTRA_DGRAM_SEND_REQ;
  3506.     Timer_GetCurrentTicks(&startTime);
  3507.     while(count > 0) {
  3508.     count--;
  3509.     itemPtr = getFreeBuffer (statePtr);
  3510.     if (itemPtr == (Address)NIL) {
  3511.         status = GEN_ABORTED_BY_SIGNAL;
  3512.         goto exit;
  3513.     }
  3514.     if (buffer != (Address) NIL) {
  3515.         bcopy((char *) buffer, itemPtr, bufSize);
  3516.     }
  3517.     dsndCount = count;
  3518. #ifndef CLEAN
  3519.     if (netHppiTrace) {
  3520.         NEXT_TRACE(statePtr, &tracePtr);
  3521.         tracePtr->event = DSND_STREAM;
  3522.         Timer_GetCurrentTicks(&curTime);
  3523.         tracePtr->ticks = curTime;
  3524.     }
  3525. #endif
  3526.     scatter.bufAddr = BUFFER_TO_DVMA(itemPtr, statePtr);
  3527.     scatter.length = bufSize;
  3528.     status = NetHppiSendReq(statePtr, SourceDone, 
  3529.             (ClientData) NIL, FALSE, 1, &scatter,
  3530.             sizeof(NetUltraDatagramRequest), &request);
  3531.     }
  3532.     Timer_GetCurrentTicks(&endTime);
  3533.     Timer_SubtractTicks(endTime, startTime, &endTime);
  3534.     Timer_TicksToTime(endTime, timePtr);
  3535. exit:
  3536.     MASTER_UNLOCK(&interPtr->mutex);
  3537.     return status;
  3538. }
  3539.  
  3540. /*
  3541.  *----------------------------------------------------------------------
  3542.  *
  3543.  * SourceDone --
  3544.  *
  3545.  *    This routine is called by the interrupt handler when a packet
  3546.  *    sent by  NetUltraSource completes.
  3547.  *
  3548.  * Results:
  3549.  *    None.
  3550.  *
  3551.  * Side effects:
  3552.  *    The write buffer associated with the command is added to
  3553.  *     the list of free write buffers.
  3554.  *
  3555.  *----------------------------------------------------------------------
  3556.  */
  3557.  
  3558. static void
  3559. SourceDone(interPtr, infoPtr)
  3560.     Net_Interface    *interPtr;    /* Interface. */
  3561.     NetUltraXRBInfo    *infoPtr;    /* Info about XRB that completed. */
  3562. {
  3563.     NetUltraRequestHdr        *hdrPtr;
  3564.     NetHppiState        *statePtr;
  3565.     List_Links            *itemPtr;
  3566.  
  3567.     hdrPtr = &(infoPtr->xrbPtr->request.dgram.hdr);
  3568.  
  3569.     statePtr = (NetHppiState *) interPtr->interfaceData;
  3570.     if (!(hdrPtr->status & NET_ULTRA_STATUS_OK)) {
  3571.     panic("SourceDone: write failed 0x%x (continuable)\n", hdrPtr->status);
  3572.     } else {
  3573. #ifndef CLEAN
  3574.     if (netHppiDebug) {
  3575.         printf("SourceDone: packet sent\n");
  3576.     }
  3577. #endif
  3578.     statePtr->numWritePending--;
  3579.     if (statePtr->numWritePending < 0) {
  3580.         panic("SourceDone: number of pending writes < 0.\n");
  3581.     }
  3582.     /*
  3583.      * Free up the write buffer. 
  3584.      */
  3585.     itemPtr = (List_Links *) VME_TO_BUFFER(hdrPtr->buffer,statePtr);
  3586.     List_Insert(itemPtr, LIST_ATREAR(statePtr->freeBufferList));
  3587.     if (statePtr->bufferAvail.waiting == TRUE) {
  3588.         Sync_Broadcast(&statePtr->bufferAvail);
  3589.     }
  3590.     }
  3591. }
  3592.  
  3593. /*
  3594.  *----------------------------------------------------------------------
  3595.  *
  3596.  * NetHppiGetStats --
  3597.  *
  3598.  *    Return the statistics for the interface.
  3599.  *
  3600.  * Results:
  3601.  *    A pointer to the statistics structure.
  3602.  *
  3603.  * Side effects:
  3604.  *    None.
  3605.  *
  3606.  *----------------------------------------------------------------------
  3607.  */
  3608.  
  3609. ReturnStatus
  3610. NetHppiGetStats(interPtr, statPtr)
  3611.     Net_Interface    *interPtr;        /* Current interface. */
  3612.     Net_Stats        *statPtr;        /* Statistics to return. */
  3613. {
  3614.     NetHppiState    *statePtr;
  3615.  
  3616.     statePtr = (NetHppiState *) interPtr->interfaceData;
  3617.     MASTER_LOCK(&interPtr->mutex);
  3618.     statPtr->hppi = statePtr->stats;
  3619.     MASTER_UNLOCK(&interPtr->mutex);
  3620.     return SUCCESS;
  3621. }
  3622.  
  3623.  
  3624. /*
  3625.  *----------------------------------------------------------------------
  3626.  *
  3627.  * GetStatusString --
  3628.  *
  3629.  *    Returns a string corresponding to the given status (status
  3630.  *    is a field in a NetUltraRequestHdr.
  3631.  *
  3632.  * Results:
  3633.  *    Ptr to string describing the status.
  3634.  *
  3635.  * Side effects:
  3636.  *    None.
  3637.  *
  3638.  *----------------------------------------------------------------------
  3639.  */
  3640.  
  3641. static char *
  3642. GetStatusString(status)
  3643.     unsigned char    status;
  3644. {
  3645.     static char *statusMsg[] = {
  3646.     "Unknown",                /* 0 */
  3647.     "OK",                    /* 1 */
  3648.     "FAIL: invalid request",        /* 2 */
  3649.     "OK: EOM",                /* 3 */
  3650.     "FAIL: no resources",            /* 4 */
  3651.     "OK: decide",                /* 5 */
  3652.     "FAIL: unknown reference",        /* 6 */
  3653.     "OK: closed",                /* 7 */
  3654.     "FAIL: buffer too small",        /* 8 */
  3655.     "OK; withdrawn",            /* 9 */
  3656.     "FAIL: buffer too large",        /* 10 */
  3657.     "OK: reject connection",        /* 11 */
  3658.     "FAIL: illegal request",        /* 12 */
  3659.     "OK: connection request",        /* 13 */
  3660.     "FAIL: REM abort",            /* 14 */
  3661.     "OK: closing",                /* 15 */
  3662.     "FAIL: LOC timeout",            /* 16 */
  3663.     "OK: timed-out",            /* 17 */
  3664.     "FAIL: unknown connection class",     /* 18 */
  3665.     "OK: out of sequence",            /* 19 */
  3666.     "FAIL: duplicate request",        /* 20 */
  3667.     "Unknown",                /* 21 */
  3668.     "FAIL: connection rejected",        /* 22 */
  3669.     "Unknown",                /* 23 */
  3670.     "FAIL: negotiation failed",        /* 24 */
  3671.     "Unknown",                /* 25 */
  3672.     "FAIL: illegal address",        /* 26 */
  3673.     "Unknown",                /* 27 */
  3674.     "FAIL: network error",            /* 28 */
  3675.     "Unknown",                /* 29 */
  3676.     "FAIL: protocol error",            /* 30 */
  3677.     "Unknown",                /* 31 */
  3678.     "FAIL: illegal RB length",        /* 32 */
  3679.     "Unknown",                /* 33 */
  3680.     "FAIL: unknown SAP id",            /* 34 */
  3681.     "Unknown",                /* 35 */
  3682.     "FAIL: zero RB id",            /* 36 */
  3683.     "Unknown",                /* 37 */
  3684.     "FAIL: adapter down",            /* 38 */
  3685.     };
  3686.     static int numStatusMsg = sizeof(statusMsg) / sizeof(char *);
  3687.  
  3688.     if (status >= numStatusMsg) {
  3689.     return "Unknown";
  3690.     } else {
  3691.     return statusMsg[status];
  3692.     }
  3693. }
  3694.  
  3695. /*
  3696.  *----------------------------------------------------------------------
  3697.  *
  3698.  * StandardDone --
  3699.  *
  3700.  *    This is a callback routine that is called from the interrupt
  3701.  *    handler when "standard" commands complete. It copies the request
  3702.  *    from the XRB in the queue to the request structure pointed
  3703.  *    to by the XRB.  This allows the XRB to be used again.
  3704.  *    If the data field in the info structure is not NIL then it
  3705.  *    is assumed to be a pointer to a condition variable and a
  3706.  *    broadcast is done on that variable.
  3707.  *
  3708.  *
  3709.  * Results:
  3710.  *    None.
  3711.  *
  3712.  * Side effects:
  3713.  *    None.
  3714.  *    
  3715.  *
  3716.  *----------------------------------------------------------------------
  3717.  */
  3718.  
  3719. /* ARGSUSED */
  3720. static void
  3721. StandardDone(interPtr, infoPtr)
  3722.     Net_Interface    *interPtr;    /* Interface. */
  3723.     NetUltraXRBInfo    *infoPtr;    /* Info about XRB that completed. */
  3724. {
  3725.     bcopy((char *) &infoPtr->xrbPtr->request, (char *) infoPtr->requestPtr,
  3726.     infoPtr->requestSize);
  3727.     if (infoPtr->doneData != (ClientData) NIL) {
  3728.     Sync_Broadcast((Sync_Condition *) infoPtr->doneData);
  3729.     }
  3730. }
  3731.  
  3732.  
  3733. /*----------------------------------------------------------------------
  3734.  *
  3735.  * setLocalAddress --
  3736.  *
  3737.  *    Copy the current interface's network address into the passed
  3738.  *    location.
  3739.  *
  3740.  * Results:
  3741.  *    None.
  3742.  * Side effects:
  3743.  *    Copies a network address.
  3744.  *
  3745.  *----------------------------------------------------------------------
  3746.  */
  3747. static
  3748. void
  3749. setLocalAddress (interPtr, netAddrPtr)
  3750. Net_Interface*    interPtr;
  3751. char*        netAddrPtr;
  3752. {
  3753.     bcopy ((char *)&(interPtr->netAddress[NET_PROTO_RAW].address.ultra) + 1,
  3754.        netAddrPtr, 7);
  3755.     netAddrPtr[0] = 0x49;
  3756.     netAddrPtr[5] = 0xfe;
  3757.  
  3758. }
  3759.  
  3760. /*----------------------------------------------------------------------
  3761.  *
  3762.  * NetHppiCmdCallback --
  3763.  *
  3764.  *    This is the routine scheduled when a completed command is sent
  3765.  *    into the ring buffer.  It is called once for each command, and
  3766.  *    is passed the address of the buffer to deal with.  It simply
  3767.  *    calls the appropriate handler for the type of message.
  3768.  *
  3769.  * Results:
  3770.  *    none
  3771.  * Side effects:
  3772.  *    none
  3773.  *
  3774.  *----------------------------------------------------------------------
  3775.  */
  3776. void
  3777. NetHppiCmdCallback (data, callInfoPtr)
  3778. ClientData    data;
  3779. Proc_CallInfo*    callInfoPtr;
  3780. {
  3781.     Dev_HppiSendXfer*    cmdPtr;
  3782.     NetUltraXRB*    xrbPtr = (NetUltraXRB*)data;
  3783.     NetHppiConnState*    connStatePtr;
  3784.  
  3785.     cmdPtr = (Dev_HppiSendXfer*)&(xrbPtr->request);
  3786.     if (cmdPtr->hdr.magic != DEV_HPPI_DEST_MAGIC) {
  3787.     panic ("NetHppiCmdCallback: bad magic number in command (0x%x)\n",
  3788.            cmdPtr->hdr.magic);
  3789.     }
  3790.     connStatePtr = (NetHppiConnState*)cmdPtr->xrbHdr.xrbId;
  3791.     switch (cmdPtr->hdr.opcode) {
  3792.       case DEV_HPPI_SEND_ALSN:
  3793.     NetHppiConnectionAccepted ((Dev_HppiSendALSN*)cmdPtr);
  3794.     break;
  3795.       case DEV_HPPI_SEND_OPEN:
  3796.     NetHppiOpenCallback ((Dev_HppiSendOPEN*)cmdPtr);
  3797.     break;
  3798.       case DEV_HPPI_SEND_CONN:
  3799.     break;
  3800.       case DEV_HPPI_SEND_CLSE:
  3801.     /*
  3802.      * The ISO reason code will be garbage, but the cleanup code
  3803.      * will ignore it in case of an abrupt (CLSE) close.
  3804.      */
  3805.     NetHppiConnectionCleanup ((Dev_HppiSendRLSE*)cmdPtr);
  3806.     break;
  3807.       case DEV_HPPI_SEND_RLSE:
  3808.     NetHppiConnectionCleanup ((Dev_HppiSendRLSE*)cmdPtr);
  3809.     break;
  3810.       case DEV_HPPI_SEND_SEND:
  3811.       case DEV_HPPI_SEND_SEOM:
  3812.       case DEV_HPPI_SEND_RECV:
  3813.     NetHppiXferCallback ((Dev_HppiSendXfer*)cmdPtr);
  3814.     break;
  3815.       case DEV_HPPI_SEND_DRCV:
  3816.     DgramRecvDone ((Dev_HppiSendDRCV*)cmdPtr);
  3817.     break;
  3818.       case DEV_HPPI_SEND_DSND:
  3819.     DgramSendDone ((Dev_HppiSendDSND*)cmdPtr);
  3820.     break;
  3821.       default:
  3822.     printf ("NetHppiCmdCallback: unknown command (0x%x)\n",
  3823.         cmdPtr->hdr.opcode);
  3824.     break;
  3825.     }
  3826.     /*
  3827.      * Now that we're done with the packet, we can declare it empty.
  3828.      */
  3829.     xrbPtr->filled = 0;
  3830. }
  3831.  
  3832.  
  3833. /*----------------------------------------------------------------------
  3834.  *
  3835.  * NetHppiOpenCallback --
  3836.  *
  3837.  *    This procedure is called back when an open request returns.
  3838.  *    It fills in the appropriate fields in the connection state
  3839.  *    information, and then calls back the user-specified callback
  3840.  *    routine.
  3841.  *
  3842.  * Returns:
  3843.  *    none
  3844.  * Side effects:
  3845.  *    Fills in connection state data structure.
  3846.  *
  3847.  *----------------------------------------------------------------------
  3848.  */
  3849. void
  3850. NetHppiOpenCallback (openBlockPtr)
  3851. Dev_HppiSendOPEN*    openBlockPtr;
  3852. {
  3853.     Net_Interface*    interPtr;
  3854.     NetHppiConnState*    connStatePtr;
  3855.     Net_HppiConnection*    connPtr;
  3856.     Boolean        doCallback = TRUE;
  3857.  
  3858.     connStatePtr = (NetHppiConnState*)openBlockPtr->xrbHdr.xrbId;
  3859.     connPtr = (Net_HppiConnection*)openBlockPtr->xrbHdr.xrbBufId;
  3860.     interPtr = connPtr->interPtr;
  3861.     MASTER_LOCK (&interPtr->mutex);
  3862.     if (connStatePtr->flags & NET_HPPI_CONN_STATE_OPEN) {
  3863.     doCallback = FALSE;
  3864.     printf ("NetHppiOpenCallback: connection already open!\n");
  3865.     goto exit;
  3866.     } else if (!(connStatePtr->flags & NET_HPPI_CONN_STATE_INUSE)) {
  3867.     doCallback = FALSE;
  3868.     printf ("NetHppiOpenCallback: connection not in use?!\n");
  3869.     goto exit;
  3870.     }
  3871.     if (openBlockPtr->xrbHdr.status != NET_ULTRA_STATUS_OK) {
  3872.     connStatePtr->flags &= ~NET_HPPI_CONN_STATE_INUSE;
  3873.     connPtr->status = NET_NOT_CONNECTED;
  3874.     } else {
  3875.     connStatePtr->flags |= NET_HPPI_CONN_STATE_OPEN;
  3876.     connStatePtr->xrbRef = openBlockPtr->xrbHdr.xrbRef;
  3877.     connPtr->status = SUCCESS;
  3878.     }
  3879.  
  3880.   exit:
  3881.     MASTER_UNLOCK (&interPtr->mutex);
  3882.     if (doCallback) {
  3883.     (*connPtr->callbackProc)(connPtr);
  3884.     }
  3885. }
  3886.  
  3887. /*----------------------------------------------------------------------
  3888.  *
  3889.  * Net_HppiConnectionOpen --
  3890.  *
  3891.  *    Open a virtual circuit.  This must be done before attempting
  3892.  *    to listen on a virtual circuit.  The calling semantics are
  3893.  *    similar to Net_HppiConnectionListen.
  3894.  *
  3895.  * Returns:
  3896.  *    Standard Sprite return status.
  3897.  * Side effects:
  3898.  *    Sends a HPPI open request.
  3899.  *
  3900.  *----------------------------------------------------------------------
  3901.  */
  3902. ReturnStatus
  3903. Net_HppiConnectionOpen (connStatusPtr)
  3904. Net_HppiConnection*    connStatusPtr;
  3905. {
  3906.     ReturnStatus    status = SUCCESS;
  3907.     NetHppiState*    statePtr;
  3908.     NetHppiConnState*    connStatePtr;
  3909.     Dev_HppiSendOPEN    adapOpen;
  3910.     Net_Interface*    interPtr;
  3911.     int            connId;
  3912.  
  3913.     interPtr = connStatusPtr->interPtr;
  3914.     statePtr = (NetHppiState*)(interPtr->interfaceData);
  3915.     MASTER_LOCK (&interPtr->mutex);
  3916.  
  3917.     /*
  3918.      * Find a free connection ID.
  3919.      */
  3920.     for (connId = 0; connId < NET_HPPI_MAX_CONNECTIONS; connId += 1) {
  3921.     if (!(statePtr->connection[connId].flags & NET_HPPI_CONN_STATE_INUSE)){
  3922.         break;
  3923.     }
  3924.     }
  3925.     if (connId == NET_HPPI_MAX_CONNECTIONS) {
  3926.     printf ("Net_HppiConnectionListen: no connections available.\n");
  3927.     status = NET_NO_CONNECTS;
  3928.     goto exit;
  3929.     }
  3930.     connStatusPtr->connectionId = connId;
  3931.     connStatePtr = &(statePtr->connection[connId]);
  3932.     connStatePtr->userConnInfo = connStatusPtr;
  3933.     connStatePtr = &(statePtr->connection[connId]);
  3934.     connStatePtr->flags = NET_HPPI_CONN_STATE_INUSE;
  3935.     adapOpen.xrbHdr.xrbId = (uint32)connStatePtr;
  3936.     adapOpen.xrbHdr.xrbBufId = (uint32)connStatusPtr;
  3937.     adapOpen.xrbHdr.xrbRef = 0;
  3938.     adapOpen.xrbHdr.tag = 1;
  3939.     adapOpen.hdr.opcode = DEV_HPPI_SEND_OPEN;
  3940.     NetHppiSendCmd (statePtr, sizeof (adapOpen), (Address)&adapOpen,
  3941.             NET_HPPI_SRC_CMD);
  3942.   exit:
  3943.     MASTER_UNLOCK (&interPtr->mutex);
  3944.     return (status);
  3945. }
  3946.  
  3947. /*----------------------------------------------------------------------
  3948.  *
  3949.  * NetHppiConnectionAccepted --
  3950.  *
  3951.  *    This is called via callback when a request block accepting a
  3952.  *    connection comes in.  Since it's always called via a Proc_Callfunc,
  3953.  *    the connection callback is called directly at the end of the
  3954.  *    routine.
  3955.  *
  3956.  * Results:
  3957.  *    none
  3958.  * Side effects:
  3959.  *    Calls a callback routine specified when the connection was requested.
  3960.  *
  3961.  *----------------------------------------------------------------------
  3962.  */
  3963. void
  3964. NetHppiConnectionAccepted (connBlockPtr)
  3965. Dev_HppiSendALSN*    connBlockPtr;
  3966. {
  3967.     NetHppiState*    statePtr;
  3968.     NetHppiConnState*    connStatePtr;
  3969.     Net_HppiConnection*    connPtr;
  3970.     Net_Interface*    interPtr;
  3971.     Boolean        doCallback = TRUE;
  3972.  
  3973.     connStatePtr = (NetHppiConnState*)connBlockPtr->xrbHdr.xrbId;
  3974.     connPtr = connStatePtr->userConnInfo;
  3975.     interPtr = connPtr->interPtr;
  3976.     statePtr = (NetHppiState*)interPtr->interfaceData;
  3977.  
  3978.     MASTER_LOCK (&interPtr->mutex);
  3979.     if (!(connStatePtr->flags & NET_HPPI_CONN_STATE_LISTEN)) {
  3980.     MASTER_UNLOCK (&interPtr->mutex);
  3981.     printf ("NetHppiConnectionEstablish: connection %d not listening?\n",
  3982.         connPtr->connectionId);
  3983.     return;
  3984.     }
  3985.  
  3986.     if (connBlockPtr->xrbHdr.status == NET_HPPI_STATUS_CONN_REQ) {
  3987.     if (netHppiDebug) {
  3988.         printf ("NetHppiConnectionAccepted: connection requested.\n");
  3989.     }
  3990.     doCallback = FALSE;
  3991.     } else if (connBlockPtr->xrbHdr.status != NET_ULTRA_STATUS_OK) {
  3992.     if (netHppiDebug) {
  3993.         printf ("NetHppiConnectionAccepted: bad ultra status 0x%x\n",
  3994.             connBlockPtr->xrbHdr.status);
  3995.     }
  3996.     connStatePtr->flags &= ~NET_HPPI_CONN_STATE_INUSE;
  3997.     connPtr->status = NET_NOT_CONNECTED;
  3998.     } else {
  3999.     /*
  4000.      * Connection established, so set up shop.
  4001.      */
  4002.     connStatePtr->flags |= NET_HPPI_CONN_STATE_CONNECTED;
  4003.     connStatePtr->flags &= ~NET_HPPI_CONN_STATE_LISTEN;
  4004.     connStatePtr->numOutstandingRecv = 0;
  4005.     connStatePtr->numOutstandingSend = 0;
  4006.     List_Init (&connStatePtr->sendHdr);
  4007.     List_Init (&connStatePtr->recvHdr);
  4008.     connPtr->status = SUCCESS;
  4009.     }
  4010.     MASTER_UNLOCK (&interPtr->mutex);
  4011.     if (doCallback) {
  4012.     if (netHppiDebug) {
  4013.         printf ("NetHppiConnectionAccepted: doing user callback.\n");
  4014.     }
  4015.     (*connPtr->callbackProc)(connPtr);
  4016.     }
  4017. }
  4018.  
  4019. /*----------------------------------------------------------------------
  4020.  *
  4021.  * Net_HppiConnectionListen --
  4022.  *
  4023.  *    Send an ALSN command to the HIPPI boards, and wait for a
  4024.  *    connection request.  When one is received, the callback
  4025.  *    routine will be called.
  4026.  *
  4027.  * Results:
  4028.  *    Standard Sprite return status.
  4029.  * Side effects:
  4030.  *    Sends ALSN command to Ultra hub.
  4031.  *
  4032.  *----------------------------------------------------------------------
  4033.  */
  4034. ReturnStatus
  4035. Net_HppiConnectionListen (connStatusPtr)
  4036. Net_HppiConnection*    connStatusPtr;
  4037. {
  4038.     ReturnStatus    status = SUCCESS;
  4039.     NetHppiState    *statePtr;
  4040.     NetHppiConnState    *connStatePtr;
  4041.     Dev_HppiSendALSN    adapListen;
  4042.     Net_Interface*    interPtr;
  4043.  
  4044.     interPtr = connStatusPtr->interPtr;
  4045.     statePtr = (NetHppiState*)(interPtr->interfaceData);
  4046.     connStatePtr = &(statePtr->connection[connStatusPtr->connectionId]);
  4047.     MASTER_LOCK (&interPtr->mutex);
  4048.     if (!(statePtr->flags & NET_HPPI_STATE_START)) {
  4049.     printf ("Net_HppiConnectionListen: adapter not started!\n");
  4050.     status = FAILURE;
  4051.     goto exit;
  4052.     }
  4053.     if (!(connStatePtr->flags & NET_HPPI_CONN_STATE_OPEN)) {
  4054.     printf ("Net_HppiConnectionListen: channel not open!\n");
  4055.     status = FAILURE;
  4056.     goto exit;
  4057.     }
  4058.  
  4059.     if (netHppiDebug) {
  4060.     printf ("Net_HppiConnectionListen: using connection %d\n",
  4061.         connStatusPtr->connectionId);
  4062.     }
  4063.     connStatePtr->flags |= NET_HPPI_CONN_STATE_LISTEN;
  4064.     adapListen.xrbHdr.xrbRef = connStatePtr->xrbRef;
  4065.     adapListen.xrbHdr.xrbId = (uint32)connStatePtr;
  4066.     adapListen.xrbHdr.xrbBufId = (uint32)connStatusPtr;
  4067.     adapListen.xrbHdr.tag = 1;
  4068.     adapListen.hdr.opcode = DEV_HPPI_SEND_ALSN;
  4069.     bcopy (&netHppiConnPar,&adapListen.xrbConPar,sizeof(adapListen.xrbConPar));
  4070.     adapListen.xrbConPar[1] = statePtr->maxBytesPower;
  4071.     /*
  4072.      * Set remote address to wildcard.  Set local to our address.
  4073.      */
  4074.     bzero (&adapListen.xrbRemTA, sizeof (adapListen.xrbRemTA));
  4075.     setLocalAddress (interPtr, &(adapListen.xrbLocTA));
  4076.     bcopy (statePtr->curTsap, adapListen.tsap, sizeof (adapListen.tsap));
  4077.     NetHppiSendCmd (statePtr, sizeof (adapListen), (Address)&adapListen,
  4078.             NET_HPPI_SRC_CMD);
  4079.  
  4080.   exit:
  4081.     MASTER_UNLOCK (&interPtr->mutex);
  4082.     return status;
  4083. }
  4084.  
  4085. /*----------------------------------------------------------------------
  4086.  *
  4087.  * NetHppiConnectionCleanup --
  4088.  *
  4089.  *    Tear down the state associated with a connection.  This aborts
  4090.  *    all outstanding requests and frees the connection to be reused.
  4091.  *    It is called when a request block indicating a closed connection
  4092.  *    is received.  This could be the result of either end wanting
  4093.  *    to close the connection.
  4094.  *
  4095.  * Results:
  4096.  *    Standard Sprite return status.
  4097.  * Side effects:
  4098.  *    Many callbacks are scheduled.
  4099.  *
  4100.  *----------------------------------------------------------------------
  4101.  */
  4102. static
  4103. void
  4104. NetHppiConnectionCleanup (cmdPtr)
  4105. Dev_HppiSendRLSE*    cmdPtr;
  4106. {
  4107.     NetHppiState*    statePtr;
  4108.     NetHppiConnState*    connStatePtr;
  4109.     Net_Interface*    interPtr;
  4110.     Net_HppiConnection*    connPtr;
  4111.     List_Links        freeUpList;
  4112.     Net_HppiDataRequest* reqPtr;
  4113.  
  4114.     connStatePtr = (NetHppiConnState*)cmdPtr->xrbHdr.xrbId;
  4115.     connPtr = (Net_HppiConnection*)cmdPtr->xrbHdr.xrbBufId;
  4116.     statePtr = connStatePtr->statePtr;
  4117.     interPtr = statePtr->interPtr;
  4118.  
  4119.     /*
  4120.      * At this point, we can free up any remaining data requests,
  4121.      * as the connection has been officially closed.
  4122.      */
  4123.     List_Init (&freeUpList);
  4124.     MASTER_LOCK (&interPtr->mutex);
  4125.     List_ListInsert (&connStatePtr->recvHdr, LIST_ATFRONT (&freeUpList));
  4126.     List_ListInsert (&connStatePtr->sendHdr, LIST_ATFRONT (&freeUpList));
  4127.     /*
  4128.      * Now that we've pulled the lists off the state pointer, the connection
  4129.      * may be reused (even before we've made all the callbacks for the
  4130.      * old connection), so mark the connection as free.
  4131.      */
  4132.     connStatePtr->flags = 0;
  4133.     MASTER_UNLOCK (&interPtr->mutex);
  4134.  
  4135.     /*
  4136.      * Send a callback for each of the still-outstanding requests.
  4137.      */
  4138.     while (!List_IsEmpty (&freeUpList)) {
  4139.     reqPtr = (Net_HppiDataRequest*)List_First (&freeUpList);
  4140.     List_Remove ((List_Links*)reqPtr);
  4141.     freeSgTag (statePtr, reqPtr->status);
  4142.     reqPtr->status = GEN_ABORTED_BY_SIGNAL;
  4143.     (*reqPtr->callbackProc)(reqPtr);
  4144.     }
  4145.     /*
  4146.      * Callback to indicate that the connection has finished closing.
  4147.      */
  4148.     (*connPtr->callbackProc)(connPtr);
  4149. }
  4150.  
  4151. /*----------------------------------------------------------------------
  4152.  *
  4153.  * Net_HppiConnectionClose --
  4154.  *
  4155.  *    Close a connection that was already open.  This routine will
  4156.  *    call the routine to actually send a close packet to the adapter.
  4157.  *    The connection state won't be nuked until the close packet
  4158.  *    successfully returns.
  4159.  *
  4160.  * Results:
  4161.  *    Sprite return status.
  4162.  * Side effects:
  4163.  *    A HIPPI connection is closed.
  4164.  *
  4165.  *----------------------------------------------------------------------
  4166.  */
  4167. ReturnStatus
  4168. Net_HppiConnectionClose (connPtr)
  4169. Net_HppiConnection*    connPtr;
  4170. {
  4171.     ReturnStatus    status = SUCCESS;
  4172.     Dev_HppiSendRLSE    rlseCmd;
  4173.     Net_Interface*    interPtr;
  4174.     NetHppiState*    statePtr;
  4175.     NetHppiConnState*    connStatePtr;
  4176.  
  4177.     if ((connPtr->connectionId < 0) ||
  4178.     (connPtr->connectionId > NET_HPPI_MAX_CONNECTIONS)) {
  4179.     return (FAILURE);
  4180.     }
  4181.     interPtr = connPtr->interPtr;
  4182.     statePtr = (NetHppiState*)interPtr->interfaceData;
  4183.     connStatePtr = &(statePtr->connection[connPtr->connectionId]);
  4184.     MASTER_LOCK (&interPtr->mutex);
  4185.     if (!(connStatePtr->flags & NET_HPPI_CONN_STATE_CONNECTED)) {
  4186.     if (netHppiDebug) {
  4187.         printf ("Net_HppiConnectionClose: connection %d not connected.\n",
  4188.             connPtr->connectionId);
  4189.     }
  4190.     status = NET_NOT_CONNECTED;
  4191.     goto exit;
  4192.     }
  4193.     connStatePtr->flags &= ~NET_HPPI_CONN_STATE_CONNECTED;
  4194.     rlseCmd.xrbHdr.xrbId = (uint32)connStatePtr;
  4195.     rlseCmd.xrbHdr.xrbBufId = (uint32)connPtr;
  4196.     rlseCmd.xrbHdr.xrbRef = connStatePtr->xrbRef;
  4197.     rlseCmd.xrbHdr.tag = 1;
  4198.     rlseCmd.hdr.opcode = DEV_HPPI_SEND_RLSE;
  4199.     status =  NetHppiSendCmd (statePtr, sizeof (rlseCmd), (Address)&rlseCmd,
  4200.                   NET_HPPI_SRC_CMD);
  4201.   exit:
  4202.     MASTER_UNLOCK (&interPtr->mutex);
  4203.     if (status != SUCCESS) {
  4204.     printf ("Net_HppiConnectionClose: couldn't send RLSE command.\n");
  4205.     }
  4206.  
  4207.     return status;
  4208. }
  4209.  
  4210. /*----------------------------------------------------------------------
  4211.  *
  4212.  * NetHppiXferCallback --
  4213.  *
  4214.  *    The callback for data being sent or received.  Translate the Ultra
  4215.  *    status into some kind of return code, and fill in the field in
  4216.  *    the transfer request block.  Unhook the block from the connection
  4217.  *    state, and then callback the upper-level routine.
  4218.  *
  4219.  *----------------------------------------------------------------------
  4220.  */
  4221. void
  4222. NetHppiXferCallback (cmdPtr)
  4223. Dev_HppiSendXfer*    cmdPtr;
  4224. {
  4225.     Net_HppiDataRequest*    dataReqPtr;
  4226.     NetHppiConnState*        connStatePtr;
  4227.     NetHppiState*        statePtr;
  4228.  
  4229.     dataReqPtr = (Net_HppiDataRequest*)cmdPtr->xrbHdr.xrbBufId;
  4230.     connStatePtr = (NetHppiConnState*)cmdPtr->xrbHdr.xrbId;
  4231.     statePtr = connStatePtr->statePtr;
  4232.     if (netHppiDebug) {
  4233.     printf ("NetHppiXferCallback: returning call for request at 0x%x\n",
  4234.         dataReqPtr);
  4235.     }
  4236.  
  4237.     MASTER_LOCK (&statePtr->interPtr->mutex);
  4238.     if (!(connStatePtr->flags & NET_HPPI_CONN_STATE_CONNECTED)) {
  4239.     if (netHppiDebug) {
  4240.         printf ("NetHppiXferCallback: connection no longer valid.\n");
  4241.     }
  4242.     MASTER_UNLOCK (&statePtr->interPtr->mutex);
  4243.     return;
  4244.     }
  4245.     freeSgTag (statePtr, dataReqPtr->status);
  4246.     if (cmdPtr->xrbHdr.status & NET_ULTRA_STATUS_OK) {
  4247.     dataReqPtr->status = SUCCESS;
  4248.     } else {
  4249.     if (netHppiDebug) {
  4250.         printf ("NetHppiXferCallback: got bad status 0x%x\n",
  4251.             cmdPtr->xrbHdr.status);
  4252.     }
  4253.     dataReqPtr->status = FAILURE;
  4254.     }
  4255.  
  4256.     List_Remove ((List_Links*)dataReqPtr);
  4257.     if (cmdPtr->hdr.opcode == DEV_HPPI_SEND_RECV) {
  4258.     connStatePtr->numOutstandingRecv -= 1;
  4259.     } else {
  4260.     connStatePtr->numOutstandingSend -= 1;
  4261.     }
  4262.     /*
  4263.      * Copy the actual transfer size back to the data request block.
  4264.      */
  4265.     dataReqPtr->xferSize = cmdPtr->cnt;
  4266.     MASTER_UNLOCK (&statePtr->interPtr->mutex);
  4267.  
  4268.     /*
  4269.      * Unmap buffers here if necessary (not yet implemented).
  4270.      */
  4271.     (*dataReqPtr->callbackProc)(dataReqPtr);
  4272. }
  4273.  
  4274. /*----------------------------------------------------------------------
  4275.  *
  4276.  * NetHppiXferData --
  4277.  *
  4278.  *    Common code for sending or receiving data on an established
  4279.  *    connection.  The data is mapped into VME space if necessary.
  4280.  *    Next, the appropriate scatter-gather array is sent to the
  4281.  *    DST board.  Finally, the request block is sent out to the
  4282.  *    SRC board.
  4283.  *
  4284.  * Returns:
  4285.  *    Standard Sprite return status.
  4286.  * Side effects:
  4287.  *    none
  4288.  *
  4289.  *----------------------------------------------------------------------
  4290.  */
  4291. static
  4292. ReturnStatus
  4293. NetHppiXferData (connPtr, dataReqPtr, which)
  4294. Net_HppiConnection*    connPtr;    /* -> connection id block */
  4295. Net_HppiDataRequest*    dataReqPtr;    /* -> data request */
  4296. int            which;        /* send or receive? */
  4297. {
  4298.     NetHppiState*    statePtr;
  4299.     NetHppiConnState*    connStatePtr;
  4300.     Dev_HppiSendXfer    sendCmd;
  4301.     Dev_HppiScatterGather sgCmd;
  4302.     Net_Interface*    interPtr = connPtr->interPtr;
  4303.     ReturnStatus    status = SUCCESS;
  4304.     int            sgCmdSize;
  4305.     int            i;
  4306.  
  4307.     statePtr = (NetHppiState *)connPtr->interPtr->interfaceData;
  4308.     if ((connPtr->connectionId < 0) ||
  4309.     (connPtr->connectionId > NET_HPPI_MAX_CONNECTIONS)) {
  4310.     if (netHppiDebug) {
  4311.         printf ("NetHppiXferData: bad connection id (%d)\n",
  4312.             connPtr->connectionId);
  4313.     }
  4314.     return (FAILURE);
  4315.     }
  4316.     connStatePtr = &(statePtr->connection[connPtr->connectionId]);
  4317.  
  4318.     MASTER_LOCK (&interPtr->mutex);
  4319.     if (!(connStatePtr->flags & NET_HPPI_CONN_STATE_CONNECTED)) {
  4320.     status = NET_NOT_CONNECTED;
  4321.     goto exit;
  4322.     }
  4323.     /*
  4324.      * Set up the scatter-gather command.  Map in buffers if necessary.
  4325.      */
  4326.     for (i = 0; i < dataReqPtr->sgSize; i++) {
  4327.     sgCmd.element[i].size = dataReqPtr->sg[i].length;
  4328.     /*
  4329.      * Must map buffer into VME if necessary.  This isn't done yet.
  4330.      */
  4331.     sgCmd.element[i].address = (uint32)dataReqPtr->sg[i].addr;
  4332.     }
  4333.     sgCmd.size = dataReqPtr->sgSize;
  4334.     sgCmd.offset = dataReqPtr->xferOffset;
  4335.     sgCmd.hdr.opcode = DEV_HPPI_SCATTER_GATHER;
  4336.     sgCmdSize = sizeof (sgCmd) - sizeof (sgCmd.element) +
  4337.     (sgCmd.size * sizeof (sgCmd.element[0]));
  4338.  
  4339.     if ((sgCmd.tag = getSgTag (statePtr)) == -1) {
  4340.     status = FAILURE;
  4341.     goto exit;
  4342.     }
  4343.  
  4344.     dataReqPtr->status = sendCmd.xrbHdr.tag = sgCmd.tag;
  4345.     if (netHppiDebug) {
  4346.     printf ("NetHppiXferData: setting SG tag to %d\n", dataReqPtr->status);
  4347.     }
  4348.     /*
  4349.      * Add the request to the chain associated with the connection.
  4350.      */
  4351.     if (which == NET_HPPI_SEND) {
  4352.     if (connStatePtr->numOutstandingSend >= connPtr->outstandingSends) {
  4353.         status = GEN_ENOENT;
  4354.         goto exit;
  4355.     }
  4356.     connStatePtr->numOutstandingSend += 1;
  4357.     List_Insert ((List_Links *)dataReqPtr, &(connStatePtr->sendHdr));
  4358.     } else {
  4359.     if (connStatePtr->numOutstandingRecv >= connPtr->outstandingRecvs) {
  4360.         status = GEN_ENOENT;
  4361.         goto exit;
  4362.     }
  4363.     connStatePtr->numOutstandingRecv += 1;
  4364.     List_Insert ((List_Links *)dataReqPtr, &(connStatePtr->recvHdr));
  4365.     }
  4366.     /*
  4367.      * Send the scatter-gather command to the DST board.
  4368.      */
  4369.     status = NetHppiSendCmd (statePtr, sgCmdSize, (Address)&sgCmd,
  4370.                  NET_HPPI_DST_CMD);
  4371.     if (status != SUCCESS) {
  4372.     goto exit;
  4373.     }
  4374.  
  4375.     /*
  4376.      * Build the data request command and send it to the SRC board.
  4377.      */
  4378.     sendCmd.xrbHdr.tag = sgCmd.tag;
  4379.     sendCmd.xrbHdr.xrbRef = connStatePtr->xrbRef;
  4380.     sendCmd.xrbHdr.xrbId = (uint32)connStatePtr;
  4381.     sendCmd.xrbHdr.xrbBufId = (uint32)dataReqPtr;
  4382.     sendCmd.cnt = dataReqPtr->xferSize;
  4383.     if (which == NET_HPPI_SEND) {
  4384.     sendCmd.hdr.opcode = DEV_HPPI_SEND_SEND;
  4385.     } else {
  4386.     sendCmd.hdr.opcode = DEV_HPPI_SEND_RECV;
  4387.     }
  4388.     status = NetHppiSendCmd (statePtr, sizeof (sendCmd), (Address)&sendCmd,
  4389.                  NET_HPPI_SRC_CMD);
  4390.   exit:
  4391.     MASTER_UNLOCK (&interPtr->mutex);
  4392.     return status;
  4393. }
  4394.  
  4395. /*----------------------------------------------------------------------
  4396.  *
  4397.  * Net_HppiSendData --
  4398.  *
  4399.  *    Send data over an established connection.
  4400.  *
  4401.  * Results:
  4402.  *    Standard Sprite return status.
  4403.  * Side effects:
  4404.  *    Data sent over the HIPPI boards.
  4405.  *
  4406.  *----------------------------------------------------------------------
  4407.  */
  4408. ReturnStatus
  4409. Net_HppiSendData (connPtr, dataReqPtr)
  4410. Net_HppiConnection*    connPtr;
  4411. Net_HppiDataRequest*    dataReqPtr;
  4412. {
  4413.     return (NetHppiXferData (connPtr, dataReqPtr, NET_HPPI_SEND));
  4414. }
  4415.  
  4416. /*----------------------------------------------------------------------
  4417.  *
  4418.  * Net_HppiReceiveData --
  4419.  *
  4420.  *    Queue up a request to receive data over an established connection.
  4421.  *    The callback routine will be called when all of the data is
  4422.  *    received.  The data must be contiguous within the connection (ie,
  4423.  *    only one start offset and length), but may be placed according
  4424.  *    to the request's scatter-gather array.
  4425.  *
  4426.  * Results:
  4427.  *    Standard Sprite return status.
  4428.  * Side effects:
  4429.  *    Requests that data be received.
  4430.  *
  4431.  *----------------------------------------------------------------------
  4432.  */
  4433. ReturnStatus
  4434. Net_HppiReceiveData (connPtr, dataReqPtr)
  4435. Net_HppiConnection*    connPtr;
  4436. Net_HppiDataRequest*    dataReqPtr;
  4437. {
  4438.     return (NetHppiXferData (connPtr, dataReqPtr, NET_HPPI_RECV));
  4439. }
  4440.  
  4441. /*----------------------------------------------------------------------
  4442.  *
  4443.  * iocConnCallback
  4444.  *
  4445.  *    Callback for the IOC connection call.  This wakes up the waiting
  4446.  *    IOC.
  4447.  *
  4448.  *----------------------------------------------------------------------
  4449.  */
  4450. static
  4451. void
  4452. iocConnCallback (connPtr)
  4453. Net_HppiConnection*    connPtr;
  4454. {
  4455.     Sync_Broadcast ((Sync_Condition *) connPtr->userData);
  4456. }
  4457.  
  4458. static
  4459. void
  4460. iocXferCallback (dataReqPtr)
  4461. Net_HppiDataRequest*    dataReqPtr;
  4462. {
  4463.     Sync_Broadcast ((Sync_Condition *) dataReqPtr->userData);
  4464. }
  4465.